diff --git a/src/rgbcx/BC1/OrderTable.cpp b/src/rgbcx/BC1/OrderTable.cpp index 1bfcdb7..c3a0ea1 100644 --- a/src/rgbcx/BC1/OrderTable.cpp +++ b/src/rgbcx/BC1/OrderTable.cpp @@ -321,997 +321,6 @@ const OrderTable<3>::BestOrderArray OrderTable<3>::BestOrders = { {1, 7, 8, 29, 56, 0, 10, 14, 2, 42, 72, 5, 4, 65, 3, 30, 84, 94, 67, 9, 25, 133, 111, 11, 32, 108, 16, 63, 21, 96, 26, 48}}}; // endregion -// region BestOrderTable4 -template <> -const OrderTable<4>::BestOrderArray OrderTable<4>::BestOrders = {{ -#if RGBCX_USE_SMALLER_TABLES - {202, 120, 13, 318, 15, 23, 403, 450, 5, 51, 260, 128, 77, 21, 33, 494, 515, 523, 4, 141, 269, 1, 2, 700, 137, 49, 48, 102, 7, 64, 753, 82}, - {13, 141, 23, 217, 115, 51, 77, 2, 64, 21, 0, 4, 5, 317, 137, 269, 202, 33, 318, 7, 291, 352, 9, 10, 3, 180, 32, 6, 365, 102, 341, 349}, - {29, 58, 262, 1, 52, 74, 6, 171, 5, 287, 151, 334, 27, 500, 75, 26, 331, 223, 53, 635, 220, 19, 50, 45, 46, 17, 14, 396, 163, 409, 324, 70}, - {40, 51, 33, 453, 14, 23, 62, 56, 12, 196, 730, 475, 153, 99, 403, 775, 117, 130, 585, 34, 4, 17, 162, 11, 139, 57, 102, 38, 108, 47, 123, 440}, - {33, 23, 51, 13, 102, 64, 202, 128, 12, 40, 15, 196, 153, 10, 1, 2, 77, 99, 141, 0, 515, 5, 117, 3, 120, 403, 700, 165, 22, 14, 269, 453}, - {13, 23, 51, 4, 77, 141, 202, 33, 115, 64, 32, 128, 0, 11, 177, 40, 15, 102, 2, 217, 7, 137, 269, 21, 90, 59, 515, 1, 180, 403, 22, 6}, - {26, 235, 19, 47, 648, 624, 78, 145, 27, 112, 122, 64, 444, 6, 630, 453, 25, 42, 65, 130, 711, 85, 390, 113, 416, 108, 665, 29, 730, 138, 644, 95}, - {64, 141, 352, 751, 217, 247, 237, 437, 177, 269, 86, 954, 947, 875, 32, 318, 95, 77, 304, 92, 597, 180, 232, 291, 128, 864, 349, 588, 372, 202, 312, 1}, - {642, 898, 180, 638, 901, 341, 82, 197, 10, 951, 15, 515, 165, 762, 700, 253, 811, 753, 752, 365, 143, 479, 244, 569, 8, 110, 351, 873, 55, 31, 499, 116}, - {221, 23, 51, 125, 438, 254, 13, 21, 39, 49, 308, 656, 0, 115, 530, 159, 158, 401, 30, 166, 912, 386, 165, 688, 518, 9, 105, 627, 424, 22, 421, 33}, - {143, 31, 1, 44, 197, 8, 180, 125, 116, 55, 13, 498, 23, 341, 638, 242, 93, 15, 2, 141, 0, 901, 752, 115, 36, 206, 165, 479, 338, 365, 515, 762}, - {12, 23, 51, 13, 14, 15, 37, 99, 515, 38, 700, 117, 2, 196, 134, 153, 753, 64, 54, 33, 128, 120, 21, 0, 328, 5, 139, 82, 453, 719, 457, 1}, - {13, 15, 23, 515, 961, 700, 457, 753, 51, 115, 4, 165, 197, 2, 38, 569, 1, 474, 0, 37, 99, 719, 5, 12, 629, 14, 11, 3, 33, 77, 64, 10}, - {15, 515, 700, 753, 1, 0, 2, 4, 3, 23, 134, 12, 961, 5, 10, 197, 11, 33, 82, 120, 457, 51, 165, 7, 6, 341, 217, 21, 77, 9, 40, 180}, - {13, 51, 23, 457, 719, 961, 730, 401, 165, 453, 0, 117, 386, 15, 134, 1, 758, 153, 12, 54, 515, 99, 11, 2, 700, 5, 753, 4, 308, 33, 6, 899}, - {134, 898, 82, 117, 13, 33, 77, 102, 23, 260, 341, 351, 120, 901, 197, 153, 961, 111, 196, 110, 180, 457, 854, 10, 450, 8, 165, 40, 4, 115, 0, 365}, - {60, 18, 126, 167, 35, 16, 191, 71, 24, 92, 121, 271, 68, 107, 212, 146, 118, 150, 199, 7, 21, 1, 9, 575, 727, 5, 566, 48, 0, 132, 108, 273}, - {62, 136, 129, 123, 128, 41, 162, 17, 249, 211, 214, 789, 618, 710, 38, 678, 248, 507, 57, 64, 152, 269, 119, 3, 177, 183, 597, 106, 4, 179, 216, 90}, - {403, 523, 51, 475, 494, 453, 817, 899, 202, 23, 450, 13, 421, 120, 102, 730, 33, 128, 4, 1, 805, 5, 7, 153, 757, 260, 318, 196, 77, 457, 326, 65}, - {4, 59, 3, 62, 12, 33, 56, 193, 27, 21, 102, 17, 40, 77, 76, 84, 32, 0, 6, 123, 119, 177, 128, 11, 18, 611, 605, 25, 13, 51, 73, 210}, - {43, 20, 319, 422, 414, 945, 0, 7, 819, 61, 5, 376, 325, 173, 804, 904, 470, 693, 97, 707, 14, 49, 22, 104, 147, 107, 95, 32, 426, 1, 330, 577}, - {13, 23, 51, 2, 0, 115, 4, 141, 217, 33, 10, 77, 1, 15, 64, 180, 3, 515, 7, 6, 22, 102, 11, 5, 40, 9, 165, 700, 202, 197, 317, 341}, - {28, 49, 0, 105, 1, 24, 65, 159, 35, 55, 95, 239, 16, 2, 109, 7, 9, 14, 170, 320, 347, 168, 424, 158, 10, 301, 124, 5, 67, 21, 64, 36}, - {15, 515, 700, 753, 0, 1, 13, 2, 117, 4, 12, 10, 5, 165, 457, 3, 9, 134, 11, 7, 6, 51, 77, 64, 961, 82, 33, 197, 14, 341, 120, 141}, - {7, 71, 14, 149, 97, 18, 60, 16, 150, 92, 398, 189, 140, 124, 24, 273, 35, 2, 69, 302, 154, 68, 0, 336, 517, 43, 66, 28, 118, 251, 230, 1}, - {4, 102, 33, 77, 40, 59, 11, 624, 210, 12, 128, 342, 5, 503, 91, 139, 64, 32, 25, 494, 202, 678, 416, 0, 403, 275, 21, 450, 196, 318, 523, 177}, - {25, 19, 42, 6, 122, 813, 256, 235, 85, 26, 436, 53, 297, 573, 680, 390, 445, 63, 27, 416, 80, 233, 65, 73, 389, 283, 45, 605, 194, 17, 250, 343}, - {402, 102, 202, 128, 33, 300, 403, 23, 12, 77, 40, 21, 342, 117, 483, 99, 25, 494, 6, 4, 63, 32, 84, 569, 139, 757, 475, 318, 19, 26, 196, 134}, - {158, 9, 0, 109, 39, 49, 65, 22, 35, 168, 55, 24, 68, 124, 159, 16, 185, 344, 333, 154, 254, 272, 175, 289, 1, 577, 95, 28, 105, 810, 30, 169}, - {197, 180, 115, 237, 498, 165, 2, 5, 287, 546, 400, 3, 61, 34, 509, 13, 297, 80, 341, 52, 45, 186, 58, 881, 23, 873, 468, 176, 64, 17, 311, 250}, - {120, 968, 373, 260, 704, 110, 450, 202, 137, 318, 77, 95, 269, 326, 217, 717, 661, 652, 851, 349, 93, 1, 518, 98, 827, 291, 21, 177, 82, 33, 848, 719}, - {44, 116, 144, 268, 434, 489, 367, 384, 98, 127, 918, 93, 948, 31, 206, 940, 855, 0, 203, 137, 9, 22, 617, 141, 332, 105, 393, 492, 959, 282, 299, 131}, - {13, 77, 23, 33, 51, 0, 64, 141, 102, 4, 2, 115, 1, 6, 202, 15, 10, 128, 269, 7, 177, 180, 3, 40, 22, 11, 515, 217, 117, 318, 700, 137}, - {15, 515, 700, 753, 4, 11, 141, 40, 165, 23, 64, 180, 13, 202, 32, 3, 51, 125, 5, 197, 21, 128, 0, 93, 77, 1, 120, 82, 269, 117, 110, 59}, - {176, 231, 585, 62, 34, 14, 412, 161, 56, 236, 527, 57, 17, 3, 51, 202, 4, 23, 369, 283, 128, 13, 472, 440, 84, 361, 136, 457, 381, 130, 719, 53}, - {9, 0, 180, 217, 237, 101, 141, 352, 88, 100, 230, 64, 175, 317, 115, 498, 68, 39, 30, 1, 702, 83, 213, 36, 365, 208, 752, 13, 252, 321, 952, 546}, - {28, 9, 22, 1, 49, 0, 109, 39, 83, 95, 86, 30, 13, 105, 128, 55, 141, 168, 158, 67, 31, 159, 208, 12, 96, 5, 185, 2, 160, 64, 137, 23}, - {72, 4, 38, 12, 51, 89, 477, 11, 57, 76, 401, 308, 23, 474, 99, 148, 413, 179, 59, 13, 431, 152, 54, 569, 17, 3, 205, 629, 197, 421, 405, 15}, - {457, 13, 23, 961, 15, 51, 515, 700, 165, 12, 753, 629, 11, 1, 719, 117, 0, 3, 2, 37, 569, 197, 40, 328, 33, 5, 153, 134, 99, 64, 38, 196}, - {254, 100, 310, 9, 30, 1, 39, 625, 166, 265, 190, 0, 272, 557, 131, 731, 31, 98, 578, 688, 404, 93, 101, 88, 49, 21, 127, 264, 44, 36, 252, 478}, - {51, 23, 12, 13, 15, 128, 99, 120, 10, 202, 515, 153, 64, 82, 700, 33, 165, 2, 5, 117, 403, 1, 141, 0, 3, 196, 37, 453, 753, 197, 260, 93}, - {38, 99, 542, 139, 453, 117, 196, 23, 457, 13, 328, 111, 37, 134, 961, 11, 12, 51, 40, 775, 587, 401, 474, 54, 153, 477, 41, 629, 33, 475, 14, 277}, - {6, 85, 25, 233, 343, 91, 26, 63, 138, 29, 19, 65, 283, 4, 81, 235, 42, 122, 605, 64, 648, 256, 174, 370, 74, 389, 718, 59, 45, 194, 445, 416}, - {49, 5, 97, 20, 197, 21, 18, 193, 0, 64, 408, 729, 173, 350, 43, 422, 165, 7, 14, 104, 61, 32, 509, 713, 523, 102, 120, 95, 125, 397, 35, 232}, - {144, 116, 268, 434, 384, 489, 367, 206, 93, 855, 940, 44, 98, 332, 617, 127, 959, 911, 137, 282, 203, 31, 22, 219, 141, 9, 131, 276, 417, 0, 1, 120}, - {17, 106, 64, 62, 32, 255, 136, 292, 476, 162, 129, 241, 123, 141, 41, 237, 720, 214, 209, 352, 519, 211, 186, 148, 752, 247, 507, 90, 21, 77, 197, 119}, - {2, 29, 52, 50, 5, 58, 14, 6, 27, 1, 366, 357, 45, 53, 17, 19, 171, 151, 26, 181, 133, 38, 218, 764, 287, 583, 61, 113, 3, 487, 600, 281}, - {130, 59, 196, 412, 381, 730, 711, 236, 77, 210, 202, 402, 453, 99, 401, 108, 361, 803, 291, 283, 153, 4, 57, 51, 128, 183, 14, 719, 503, 117, 23, 11}, - {13, 23, 51, 141, 77, 4, 33, 64, 115, 0, 217, 10, 180, 202, 2, 102, 11, 9, 15, 165, 40, 21, 128, 352, 22, 7, 197, 3, 317, 515, 269, 1}, - {23, 13, 202, 51, 120, 15, 21, 5, 141, 1, 128, 269, 137, 515, 64, 102, 125, 48, 98, 33, 260, 523, 318, 93, 700, 165, 450, 77, 2, 12, 403, 82}, - {1, 2, 14, 46, 29, 67, 38, 52, 5, 171, 58, 24, 103, 69, 96, 70, 83, 181, 54, 75, 163, 223, 16, 45, 112, 309, 155, 0, 186, 35, 18, 108}, - {15, 515, 700, 753, 13, 0, 1, 2, 153, 5, 23, 10, 117, 3, 9, 7, 134, 165, 12, 6, 341, 33, 4, 14, 77, 457, 115, 21, 719, 180, 217, 82}, - {197, 165, 509, 13, 391, 180, 308, 115, 23, 546, 5, 498, 2, 29, 3, 401, 901, 61, 34, 80, 14, 457, 250, 569, 237, 873, 38, 297, 45, 15, 468, 386}, - {19, 73, 27, 250, 200, 714, 444, 472, 26, 53, 34, 17, 813, 322, 283, 390, 128, 297, 78, 123, 432, 14, 436, 136, 106, 690, 57, 122, 389, 80, 503, 3}, - {3, 17, 21, 45, 62, 32, 38, 12, 155, 14, 2, 328, 5, 99, 401, 536, 828, 13, 227, 488, 106, 51, 719, 119, 540, 76, 165, 221, 115, 629, 209, 41}, - {115, 341, 873, 197, 365, 13, 901, 180, 569, 752, 317, 1, 10, 498, 143, 634, 261, 0, 509, 15, 943, 237, 44, 31, 116, 601, 165, 127, 282, 23, 141, 64}, - {453, 51, 23, 403, 33, 421, 475, 102, 15, 153, 196, 515, 13, 700, 117, 523, 12, 40, 753, 21, 4, 134, 0, 494, 670, 899, 22, 801, 730, 10, 11, 401}, - {23, 13, 51, 33, 12, 117, 153, 134, 453, 196, 15, 99, 515, 40, 14, 700, 128, 102, 11, 753, 77, 64, 403, 202, 0, 401, 475, 37, 65, 2, 3, 38}, - {2, 7, 5, 14, 70, 1, 29, 61, 52, 45, 6, 112, 66, 16, 21, 32, 592, 46, 38, 135, 87, 58, 186, 315, 290, 128, 113, 0, 64, 48, 227, 23}, - {33, 23, 102, 51, 128, 13, 64, 202, 141, 1, 77, 10, 153, 40, 196, 117, 2, 3, 0, 5, 15, 269, 403, 12, 137, 134, 318, 165, 120, 6, 453, 99}, - {16, 92, 7, 20, 43, 35, 126, 71, 60, 14, 107, 18, 68, 97, 0, 121, 279, 149, 24, 246, 191, 48, 118, 575, 55, 140, 362, 783, 230, 150, 375, 566}, - {13, 23, 4, 33, 77, 64, 51, 102, 141, 128, 32, 10, 0, 202, 40, 115, 59, 22, 90, 11, 177, 21, 291, 6, 7, 318, 180, 117, 137, 2, 95, 165}, - {507, 162, 129, 41, 4, 211, 62, 38, 123, 59, 57, 248, 183, 130, 99, 11, 3, 361, 202, 17, 402, 556, 266, 305, 803, 210, 128, 184, 152, 136, 313, 117}, - {643, 123, 193, 650, 802, 18, 25, 389, 718, 256, 65, 289, 84, 91, 619, 511, 415, 90, 235, 63, 57, 510, 324, 216, 862, 102, 6, 183, 108, 397, 217, 736}, - {13, 23, 15, 1, 515, 51, 0, 2, 700, 5, 753, 165, 141, 115, 12, 3, 4, 180, 21, 197, 457, 7, 6, 10, 120, 9, 33, 202, 77, 32, 8, 11}, - {23, 51, 13, 453, 64, 403, 12, 21, 5, 202, 128, 475, 165, 141, 523, 95, 125, 115, 3, 1, 4, 730, 120, 32, 2, 494, 180, 719, 457, 197, 450, 401}, - {204, 74, 135, 66, 6, 174, 192, 7, 138, 172, 85, 353, 348, 580, 280, 97, 95, 500, 29, 64, 426, 32, 87, 889, 65, 81, 25, 2, 52, 43, 568, 673}, - {35, 0, 68, 69, 24, 9, 1, 16, 65, 103, 149, 133, 18, 114, 28, 50, 83, 2, 189, 7, 46, 14, 101, 336, 175, 124, 251, 55, 71, 218, 38, 238}, - {16, 101, 0, 118, 9, 18, 24, 68, 35, 154, 71, 124, 60, 212, 191, 520, 55, 806, 694, 167, 28, 39, 364, 375, 1, 346, 252, 65, 604, 302, 22, 21}, - {0, 9, 16, 35, 1, 24, 68, 18, 65, 21, 103, 67, 13, 149, 28, 189, 71, 23, 101, 238, 114, 7, 335, 133, 486, 141, 22, 212, 48, 50, 30, 118}, - {13, 202, 23, 77, 33, 51, 128, 5, 21, 141, 115, 32, 102, 64, 4, 0, 318, 269, 10, 15, 291, 2, 494, 177, 11, 217, 3, 515, 22, 137, 6, 700}, - {16, 92, 60, 35, 7, 18, 24, 68, 150, 149, 14, 71, 0, 375, 97, 126, 118, 107, 230, 191, 246, 273, 140, 55, 175, 653, 9, 575, 2, 28, 566, 517}, - {76, 90, 21, 179, 316, 148, 205, 32, 464, 288, 184, 257, 245, 1, 89, 2, 460, 57, 152, 45, 38, 358, 645, 5, 12, 449, 350, 48, 37, 17, 4, 14}, - {19, 27, 26, 813, 80, 297, 17, 495, 436, 53, 73, 200, 4, 378, 250, 59, 106, 25, 45, 128, 361, 42, 113, 469, 122, 390, 77, 40, 736, 6, 11, 136}, - {6, 26, 235, 138, 19, 145, 112, 70, 331, 262, 25, 42, 52, 624, 27, 453, 122, 47, 500, 78, 648, 85, 29, 2, 630, 632, 409, 113, 50, 226, 108, 75}, - {7, 16, 14, 24, 92, 35, 18, 2, 46, 9, 60, 140, 0, 87, 50, 5, 54, 13, 12, 38, 171, 23, 126, 21, 58, 64, 1, 70, 128, 71, 220, 163}, - {90, 205, 257, 184, 32, 179, 460, 5, 245, 45, 2, 288, 769, 524, 57, 21, 152, 229, 17, 1, 497, 4, 292, 59, 619, 452, 432, 76, 476, 11, 266, 14}, - {15, 515, 700, 753, 4, 5, 11, 141, 13, 1, 33, 3, 0, 128, 202, 23, 180, 21, 2, 64, 269, 32, 117, 134, 120, 40, 102, 318, 153, 17, 137, 352}, - {47, 130, 711, 108, 453, 412, 730, 196, 390, 283, 78, 27, 51, 183, 381, 236, 128, 200, 719, 14, 153, 472, 503, 34, 59, 250, 3, 4, 57, 803, 123, 432}, - {12, 277, 51, 474, 111, 153, 23, 99, 13, 37, 961, 94, 629, 542, 569, 431, 79, 139, 38, 134, 117, 453, 33, 188, 196, 40, 115, 15, 11, 157, 401, 515}, - {17, 495, 469, 106, 26, 378, 80, 27, 161, 483, 19, 742, 527, 436, 383, 862, 73, 136, 53, 814, 297, 6, 119, 84, 62, 56, 25, 3, 209, 611, 4, 128}, - {81, 681, 636, 91, 0, 750, 370, 104, 718, 138, 18, 693, 173, 784, 29, 397, 348, 74, 192, 673, 174, 65, 6, 207, 64, 280, 306, 52, 671, 32, 355, 319}, - {15, 515, 700, 753, 33, 77, 4, 102, 115, 117, 40, 13, 1, 153, 134, 11, 5, 217, 23, 196, 2, 21, 3, 317, 32, 365, 0, 341, 291, 59, 12, 51}, - {0, 9, 28, 35, 68, 1, 65, 67, 101, 39, 69, 175, 16, 238, 13, 22, 96, 124, 18, 24, 251, 30, 55, 12, 23, 2, 50, 141, 114, 5, 154, 103}, - {23, 33, 77, 13, 117, 40, 11, 102, 64, 4, 51, 403, 153, 453, 10, 0, 196, 134, 128, 65, 12, 291, 86, 99, 95, 59, 15, 141, 202, 180, 137, 719}, - {214, 90, 289, 6, 874, 64, 25, 65, 235, 42, 751, 249, 256, 312, 194, 85, 746, 875, 174, 32, 525, 288, 519, 835, 247, 348, 233, 544, 217, 524, 437, 352}, - {1, 22, 2, 0, 36, 67, 28, 5, 49, 95, 12, 50, 168, 83, 105, 55, 7, 9, 14, 194, 103, 23, 114, 21, 584, 46, 10, 13, 38, 69, 208, 159}, - {269, 141, 13, 202, 33, 180, 318, 77, 291, 137, 102, 352, 128, 23, 349, 51, 31, 217, 372, 317, 125, 197, 44, 21, 11, 5, 901, 1, 18, 0, 4, 494}, - {435, 144, 274, 88, 203, 418, 30, 1, 190, 410, 96, 778, 100, 530, 521, 326, 466, 795, 686, 166, 960, 321, 382, 264, 367, 822, 131, 31, 692, 9, 213, 93}, - {76, 72, 90, 21, 37, 179, 12, 205, 32, 428, 148, 38, 308, 405, 4, 413, 57, 184, 749, 245, 316, 221, 54, 645, 288, 1, 152, 155, 464, 257, 2, 14}, - {77, 33, 64, 102, 13, 141, 23, 2, 40, 1, 51, 10, 0, 115, 6, 180, 202, 128, 4, 3, 177, 269, 15, 7, 22, 165, 291, 14, 217, 318, 137, 11}, - {397, 81, 4, 32, 65, 788, 693, 804, 681, 11, 249, 21, 91, 64, 690, 494, 3, 0, 422, 56, 348, 725, 194, 123, 23, 59, 523, 319, 61, 510, 95, 90}, - {60, 126, 16, 7, 92, 121, 314, 246, 35, 107, 150, 132, 14, 146, 24, 18, 199, 298, 232, 71, 359, 140, 672, 97, 392, 649, 5, 423, 95, 21, 22, 388}, - {15, 515, 141, 217, 115, 700, 13, 23, 120, 317, 753, 180, 33, 260, 110, 137, 341, 51, 1, 365, 4, 77, 64, 202, 0, 40, 36, 352, 197, 269, 10, 21}, - {111, 134, 117, 474, 23, 13, 961, 12, 569, 431, 37, 15, 51, 115, 515, 700, 277, 99, 753, 38, 197, 405, 457, 4, 72, 94, 629, 45, 11, 89, 54, 148}, - {23, 13, 51, 5, 1, 15, 2, 21, 12, 202, 141, 0, 515, 165, 120, 32, 4, 64, 700, 3, 115, 197, 269, 125, 753, 7, 9, 128, 6, 180, 453, 403}, - {13, 141, 4, 23, 5, 2, 115, 217, 202, 51, 180, 137, 269, 352, 77, 1, 317, 3, 21, 318, 0, 15, 9, 64, 10, 197, 11, 341, 33, 515, 752, 7}, - {165, 125, 197, 13, 391, 21, 23, 558, 48, 380, 97, 120, 298, 33, 14, 426, 66, 115, 32, 386, 900, 180, 6, 98, 357, 237, 326, 509, 51, 278, 221, 457}, - {120, 82, 15, 260, 515, 1, 351, 77, 450, 700, 13, 21, 141, 23, 753, 202, 217, 93, 110, 33, 51, 854, 5, 128, 326, 102, 137, 180, 817, 48, 269, 352}, - {23, 13, 15, 51, 515, 700, 961, 753, 0, 457, 1, 2, 4, 115, 10, 453, 569, 5, 33, 165, 11, 719, 14, 40, 64, 197, 3, 21, 474, 629, 38, 401}, - {264, 166, 39, 30, 9, 100, 435, 254, 93, 921, 190, 363, 1, 625, 411, 382, 897, 656, 203, 478, 404, 812, 438, 110, 473, 88, 18, 691, 156, 141, 274, 272}, - {9, 0, 252, 100, 166, 39, 101, 265, 364, 68, 88, 329, 520, 18, 419, 676, 118, 167, 404, 604, 16, 1, 21, 30, 212, 158, 553, 49, 382, 274, 48, 13}, - {15, 515, 700, 753, 4, 11, 141, 5, 3, 13, 202, 1, 180, 21, 2, 165, 269, 23, 40, 64, 0, 318, 12, 32, 128, 51, 77, 117, 523, 197, 120, 457}, - {24, 1, 2, 69, 35, 16, 67, 18, 14, 50, 0, 46, 68, 9, 38, 7, 133, 71, 83, 149, 28, 108, 189, 218, 65, 114, 238, 29, 75, 54, 5, 96}, - {90, 289, 214, 64, 874, 13, 77, 712, 66, 751, 4, 23, 51, 192, 32, 0, 202, 194, 312, 177, 33, 65, 234, 104, 875, 288, 59, 5, 835, 416, 102, 95}, - {0, 9, 49, 127, 98, 31, 301, 28, 371, 159, 1, 395, 512, 737, 158, 761, 916, 623, 16, 44, 242, 39, 170, 18, 293, 105, 24, 272, 101, 22, 23, 385}, - {17, 62, 136, 214, 123, 129, 32, 292, 119, 209, 710, 106, 141, 162, 128, 64, 45, 4, 77, 249, 11, 618, 211, 3, 207, 130, 519, 183, 38, 177, 21, 269}, - {5, 107, 581, 356, 279, 32, 441, 362, 493, 660, 13, 298, 0, 534, 49, 147, 21, 22, 132, 121, 97, 423, 7, 590, 259, 683, 14, 786, 126, 508, 60, 246}, - {51, 13, 15, 730, 453, 23, 515, 719, 386, 457, 12, 700, 403, 475, 899, 1, 6, 523, 753, 421, 99, 401, 165, 33, 2, 19, 361, 5, 0, 670, 120, 27}, - {49, 28, 9, 159, 272, 22, 254, 131, 158, 327, 95, 105, 0, 39, 35, 168, 347, 286, 374, 55, 65, 627, 424, 912, 68, 578, 1, 24, 239, 175, 688, 169}, - {15, 515, 700, 33, 753, 4, 77, 141, 341, 317, 1, 10, 13, 180, 102, 22, 40, 117, 115, 365, 5, 901, 23, 197, 134, 11, 217, 351, 64, 82, 21, 137}, - {134, 15, 13, 515, 23, 700, 12, 753, 51, 474, 37, 961, 197, 10, 457, 569, 4, 0, 99, 2, 115, 38, 165, 153, 94, 3, 139, 11, 1, 82, 33, 5}, - {7, 2, 20, 58, 5, 14, 128, 66, 6, 29, 32, 43, 21, 52, 16, 38, 631, 61, 74, 97, 46, 135, 113, 25, 202, 192, 13, 0, 884, 45, 112, 87}, - {77, 13, 33, 202, 23, 128, 102, 4, 141, 342, 117, 0, 269, 318, 134, 22, 11, 21, 32, 153, 403, 291, 49, 64, 137, 51, 40, 15, 494, 5, 196, 98}, - {2, 1, 14, 6, 46, 38, 29, 65, 5, 36, 67, 0, 103, 7, 22, 86, 133, 50, 108, 208, 52, 83, 24, 323, 283, 69, 28, 18, 10, 25, 23, 75}, - {15, 515, 700, 753, 1, 5, 4, 2, 3, 13, 0, 11, 180, 341, 12, 33, 10, 197, 134, 365, 77, 23, 21, 901, 6, 117, 165, 7, 37, 32, 17, 102}, - {203, 268, 206, 93, 417, 940, 31, 8, 120, 137, 44, 499, 959, 473, 202, 692, 728, 559, 0, 260, 10, 326, 141, 564, 817, 127, 341, 1, 450, 22, 110, 23}, - {15, 82, 515, 120, 700, 0, 10, 753, 33, 8, 64, 165, 110, 31, 260, 93, 13, 197, 23, 22, 40, 4, 351, 44, 77, 9, 11, 153, 102, 51, 1, 196}, - {60, 0, 16, 7, 14, 43, 20, 71, 28, 10, 2, 22, 154, 18, 13, 24, 92, 1, 51, 576, 35, 615, 805, 925, 68, 126, 124, 149, 97, 64, 23, 55}, - {19, 6, 26, 80, 5, 84, 27, 17, 25, 2, 504, 129, 45, 240, 56, 123, 4, 119, 618, 1, 76, 106, 64, 51, 14, 3, 128, 65, 32, 710, 0, 42}, - {15, 515, 700, 753, 13, 4, 77, 23, 33, 51, 0, 5, 8, 10, 11, 31, 44, 1, 82, 22, 202, 64, 110, 102, 93, 21, 291, 40, 141, 180, 9, 49}, - {195, 98, 271, 223, 132, 167, 146, 407, 1, 360, 121, 834, 393, 591, 212, 199, 293, 259, 522, 107, 354, 147, 156, 191, 807, 590, 48, 18, 125, 16, 765, 541}, - {128, 202, 77, 210, 402, 318, 33, 102, 6, 40, 403, 29, 342, 269, 196, 757, 99, 139, 2, 111, 42, 4, 494, 117, 275, 300, 13, 12, 678, 0, 177, 122}, - {13, 33, 23, 40, 51, 102, 4, 117, 77, 64, 134, 0, 128, 153, 202, 196, 453, 11, 15, 12, 1, 22, 403, 141, 59, 14, 10, 475, 515, 65, 700, 95}, - {7, 16, 14, 24, 18, 2, 28, 0, 92, 71, 1, 22, 6, 35, 60, 20, 168, 10, 154, 118, 5, 302, 124, 69, 97, 109, 703, 158, 420, 12, 149, 66}, - {15, 1, 515, 23, 0, 13, 700, 2, 51, 753, 180, 5, 120, 165, 197, 21, 115, 4, 33, 9, 141, 7, 12, 6, 3, 457, 386, 202, 260, 523, 8, 31}, - {60, 107, 121, 132, 146, 126, 199, 279, 150, 92, 16, 649, 441, 35, 955, 7, 21, 0, 423, 5, 18, 195, 598, 298, 493, 356, 32, 653, 22, 362, 953, 10}, - {31, 44, 98, 276, 284, 299, 116, 935, 9, 201, 0, 131, 39, 127, 144, 662, 1, 137, 371, 492, 567, 489, 93, 254, 49, 268, 22, 28, 30, 293, 434, 737}, - {13, 15, 23, 515, 700, 0, 1, 51, 753, 4, 2, 10, 77, 202, 5, 115, 3, 165, 197, 457, 9, 12, 11, 961, 33, 120, 22, 141, 180, 7, 6, 40}, - {123, 162, 184, 257, 17, 183, 229, 130, 129, 3, 84, 136, 99, 152, 556, 383, 57, 497, 12, 205, 4, 62, 56, 452, 80, 266, 128, 14, 40, 119, 27, 106}, - {196, 33, 117, 40, 153, 23, 134, 13, 51, 102, 453, 0, 15, 475, 12, 14, 515, 2, 22, 700, 4, 21, 753, 64, 401, 670, 730, 1, 9, 11, 10, 99}, - {224, 219, 187, 131, 258, 385, 442, 871, 836, 31, 98, 908, 44, 574, 127, 944, 137, 839, 116, 36, 613, 1, 254, 39, 926, 160, 829, 96, 93, 371, 860, 827}, - {121, 195, 156, 132, 146, 360, 590, 407, 786, 522, 883, 591, 259, 929, 626, 941, 150, 687, 5, 55, 296, 379, 467, 178, 586, 465, 279, 21, 1, 13, 60, 354}, - {2, 1, 14, 29, 6, 5, 46, 52, 38, 19, 114, 75, 26, 65, 108, 96, 25, 50, 36, 70, 103, 309, 17, 236, 218, 74, 12, 86, 0, 3, 10, 112}, - {15, 515, 82, 700, 120, 753, 10, 0, 8, 197, 260, 165, 351, 64, 13, 110, 117, 93, 31, 1, 9, 33, 22, 23, 457, 44, 450, 77, 102, 898, 40, 49}, - {7, 66, 97, 2, 172, 74, 226, 52, 29, 135, 192, 232, 43, 324, 92, 5, 38, 20, 222, 14, 6, 568, 87, 107, 353, 620, 580, 16, 138, 174, 448, 32}, - {62, 129, 123, 162, 136, 249, 618, 183, 507, 57, 4, 152, 17, 59, 11, 184, 117, 77, 3, 128, 211, 41, 130, 205, 12, 40, 33, 106, 64, 229, 38, 313}, - {1, 13, 15, 2, 4, 515, 23, 0, 3, 115, 700, 5, 51, 77, 341, 141, 753, 180, 33, 217, 197, 202, 901, 6, 21, 165, 11, 365, 318, 317, 10, 102}, - {6, 26, 235, 19, 145, 47, 112, 78, 64, 27, 453, 95, 29, 444, 25, 624, 85, 108, 648, 70, 32, 130, 74, 42, 711, 630, 632, 138, 65, 122, 113, 730}, - {23, 51, 12, 15, 13, 99, 515, 153, 117, 10, 700, 37, 120, 82, 165, 2, 753, 64, 128, 0, 403, 3, 5, 1, 134, 197, 453, 31, 202, 457, 110, 21}, - {16, 24, 18, 71, 64, 35, 92, 7, 246, 146, 9, 108, 60, 118, 199, 5, 140, 2, 267, 0, 230, 830, 32, 133, 1, 68, 50, 330, 247, 563, 36, 12}, - {15, 515, 700, 753, 0, 1, 13, 2, 23, 3, 4, 217, 51, 5, 115, 8, 9, 180, 341, 10, 7, 6, 317, 77, 33, 372, 901, 197, 365, 11, 120, 165}, - {234, 639, 178, 202, 77, 142, 5, 455, 450, 49, 416, 0, 147, 427, 198, 21, 315, 329, 13, 318, 325, 557, 120, 344, 113, 259, 22, 128, 61, 105, 23, 494}, - {1, 31, 36, 44, 141, 180, 55, 2, 64, 22, 98, 116, 13, 352, 0, 115, 10, 127, 5, 164, 253, 498, 237, 165, 341, 197, 4, 86, 15, 170, 125, 23}, - {15, 120, 13, 141, 23, 260, 217, 515, 1, 77, 51, 110, 180, 700, 317, 82, 269, 137, 115, 202, 21, 753, 64, 5, 351, 291, 0, 450, 352, 93, 36, 326}, - {26, 6, 112, 396, 19, 145, 25, 122, 648, 287, 42, 74, 624, 222, 416, 45, 138, 66, 644, 151, 113, 651, 29, 573, 64, 280, 445, 27, 525, 85, 70, 58}, - {156, 360, 5, 146, 121, 21, 271, 522, 354, 132, 49, 13, 18, 195, 16, 340, 60, 591, 446, 586, 727, 0, 107, 407, 167, 48, 1, 463, 199, 566, 32, 23}, - {5, 61, 49, 147, 178, 612, 660, 120, 21, 182, 23, 427, 259, 683, 33, 4, 77, 70, 13, 3, 376, 98, 64, 0, 481, 344, 48, 595, 291, 263, 141, 51}, - {89, 79, 468, 179, 358, 205, 94, 405, 115, 498, 72, 180, 365, 431, 37, 111, 341, 734, 188, 317, 482, 217, 11, 4, 245, 152, 413, 216, 12, 474, 490, 752}, - {24, 16, 35, 68, 18, 71, 7, 92, 0, 108, 9, 14, 118, 101, 336, 175, 375, 302, 28, 124, 154, 55, 149, 60, 398, 1, 65, 2, 140, 273, 345, 230}, - {51, 730, 421, 801, 453, 386, 23, 523, 13, 475, 719, 401, 670, 365, 899, 403, 115, 457, 758, 165, 33, 494, 450, 6, 423, 805, 629, 56, 569, 514, 958, 388}, - {113, 45, 6, 311, 29, 2, 151, 614, 145, 491, 112, 80, 5, 27, 61, 74, 315, 66, 209, 631, 19, 25, 58, 17, 73, 26, 1, 243, 70, 64, 611, 287}, - {4, 339, 188, 471, 11, 59, 79, 12, 377, 94, 99, 33, 77, 102, 51, 111, 37, 152, 13, 961, 474, 542, 40, 342, 3, 23, 128, 403, 202, 177, 184, 57}, - {15, 4, 515, 11, 700, 33, 82, 40, 0, 120, 753, 10, 8, 110, 13, 93, 23, 165, 77, 260, 64, 31, 22, 51, 44, 102, 351, 1, 125, 9, 197, 21}, - {16, 24, 18, 0, 35, 68, 28, 71, 124, 118, 60, 7, 9, 55, 14, 92, 109, 101, 419, 175, 22, 252, 154, 375, 149, 302, 158, 346, 2, 49, 1, 126}, - {17, 45, 227, 21, 106, 3, 2, 243, 209, 5, 48, 32, 221, 62, 207, 50, 29, 186, 290, 270, 263, 52, 14, 496, 400, 119, 46, 255, 54, 430, 38, 721}, - {340, 354, 586, 658, 156, 195, 698, 668, 1, 296, 9, 18, 883, 363, 447, 379, 303, 98, 411, 13, 31, 163, 51, 5, 371, 48, 919, 846, 121, 21, 360, 70}, - {277, 153, 111, 12, 23, 51, 474, 99, 38, 37, 139, 117, 41, 457, 79, 453, 542, 13, 11, 33, 134, 157, 629, 188, 961, 14, 196, 401, 102, 569, 15, 94}, - {0, 18, 16, 159, 49, 24, 9, 105, 35, 68, 7, 28, 22, 1, 60, 344, 55, 101, 109, 2, 14, 158, 13, 23, 71, 118, 455, 286, 272, 424, 5, 327}, - {0, 105, 9, 49, 16, 18, 158, 28, 518, 24, 101, 320, 1, 68, 170, 301, 272, 127, 7, 286, 35, 890, 109, 39, 159, 98, 21, 344, 31, 55, 371, 23}, - {141, 1, 180, 15, 13, 2, 365, 217, 515, 352, 317, 115, 341, 0, 4, 5, 269, 700, 23, 21, 3, 752, 197, 77, 753, 51, 31, 901, 10, 202, 8, 64}, - {4, 23, 51, 33, 19, 17, 102, 153, 485, 880, 40, 403, 196, 26, 300, 453, 27, 117, 78, 0, 12, 200, 47, 5, 11, 14, 342, 99, 53, 77, 475, 2}, - {62, 184, 56, 440, 130, 229, 183, 3, 556, 152, 99, 162, 12, 266, 17, 548, 136, 57, 305, 161, 123, 14, 452, 4, 383, 403, 257, 34, 40, 84, 33, 139}, - {13, 23, 77, 141, 64, 202, 33, 51, 269, 115, 0, 102, 21, 4, 217, 128, 5, 32, 318, 137, 291, 9, 15, 2, 180, 10, 3, 317, 177, 515, 7, 6}, - {1, 22, 36, 105, 170, 0, 86, 2, 31, 28, 239, 64, 55, 5, 10, 98, 9, 44, 127, 95, 654, 67, 301, 143, 13, 12, 49, 23, 320, 141, 83, 21}, - {15, 515, 700, 753, 0, 1, 13, 2, 23, 901, 5, 8, 51, 82, 9, 180, 457, 4, 7, 12, 3, 6, 10, 120, 341, 141, 22, 898, 197, 351, 115, 260}, - {1, 39, 274, 98, 100, 265, 190, 30, 438, 310, 166, 223, 88, 96, 909, 31, 264, 625, 530, 9, 382, 812, 21, 252, 593, 0, 254, 539, 44, 131, 23, 778}, - {18, 212, 167, 118, 363, 1, 447, 411, 146, 60, 271, 16, 781, 121, 647, 9, 621, 562, 21, 478, 664, 68, 815, 5, 354, 98, 48, 101, 24, 446, 777, 463}, - {24, 28, 22, 0, 7, 1, 2, 16, 14, 65, 35, 49, 158, 95, 109, 159, 55, 105, 10, 18, 124, 9, 67, 5, 239, 149, 12, 289, 108, 68, 21, 424}, - {105, 22, 131, 272, 286, 98, 55, 239, 1, 31, 320, 9, 127, 327, 36, 185, 28, 374, 86, 219, 0, 64, 187, 44, 578, 164, 224, 913, 535, 115, 601, 13}, - {22, 31, 28, 301, 127, 98, 44, 0, 105, 1, 512, 395, 9, 293, 109, 299, 95, 338, 239, 125, 242, 116, 36, 320, 55, 841, 900, 685, 599, 23, 13, 763}, - {2, 1, 58, 29, 5, 14, 52, 46, 186, 334, 45, 155, 151, 50, 400, 75, 38, 69, 502, 61, 48, 227, 223, 7, 163, 17, 262, 67, 549, 21, 70, 113}, - {7, 107, 135, 232, 97, 14, 2, 92, 66, 16, 172, 192, 278, 387, 298, 356, 38, 35, 448, 52, 46, 43, 60, 29, 20, 126, 324, 526, 357, 359, 64, 5}, - {20, 43, 104, 426, 173, 7, 560, 414, 707, 784, 319, 81, 0, 861, 422, 819, 38, 74, 715, 52, 376, 97, 879, 32, 330, 22, 49, 64, 66, 95, 192, 526}, - {104, 74, 636, 66, 204, 0, 355, 81, 222, 25, 29, 319, 145, 784, 20, 65, 90, 4, 174, 194, 7, 64, 6, 746, 138, 173, 750, 715, 91, 43, 192, 32}, - {0, 9, 101, 35, 68, 39, 65, 28, 252, 124, 67, 154, 364, 336, 100, 166, 30, 1, 289, 55, 149, 346, 16, 114, 158, 88, 439, 24, 429, 22, 570, 194}, - {57, 14, 4, 231, 236, 585, 176, 59, 369, 23, 361, 13, 719, 51, 300, 342, 12, 457, 56, 3, 62, 38, 202, 401, 34, 46, 2, 322, 11, 215, 210, 507}, - {1, 2, 15, 3, 141, 0, 515, 5, 33, 700, 13, 64, 77, 180, 6, 128, 753, 10, 4, 269, 102, 202, 11, 7, 134, 197, 352, 120, 117, 318, 12, 291}, - {5, 1, 21, 202, 13, 32, 48, 23, 0, 61, 259, 22, 494, 120, 70, 49, 51, 18, 137, 128, 465, 12, 178, 115, 2, 453, 403, 141, 58, 3, 90, 450}, - {141, 205, 4, 72, 59, 79, 245, 11, 352, 94, 152, 76, 247, 216, 21, 188, 452, 217, 497, 12, 89, 37, 111, 339, 588, 77, 64, 875, 864, 115, 358, 464}, - {15, 515, 700, 753, 0, 1, 2, 13, 5, 4, 23, 3, 8, 341, 365, 51, 115, 10, 120, 457, 6, 141, 77, 197, 31, 7, 165, 9, 202, 450, 961, 260}, - {5, 2, 50, 14, 58, 38, 171, 46, 29, 1, 45, 186, 17, 52, 155, 218, 48, 281, 61, 487, 54, 36, 67, 21, 328, 334, 151, 227, 760, 114, 400, 133}, - {457, 120, 70, 125, 318, 64, 23, 48, 795, 291, 202, 761, 751, 415, 77, 846, 269, 758, 21, 237, 96, 260, 391, 165, 87, 1, 128, 5, 221, 13, 137, 763}, - {13, 23, 51, 33, 4, 40, 117, 102, 453, 64, 153, 196, 0, 77, 15, 11, 12, 475, 1, 65, 134, 10, 515, 22, 21, 14, 700, 59, 403, 141, 2, 753}, - {229, 152, 57, 266, 452, 381, 432, 12, 313, 184, 99, 471, 17, 4, 62, 339, 157, 3, 129, 59, 128, 11, 369, 37, 77, 38, 40, 123, 5, 497, 188, 257}, - {49, 28, 109, 22, 159, 9, 272, 95, 105, 131, 55, 35, 254, 168, 39, 327, 169, 0, 1, 286, 175, 374, 347, 158, 420, 67, 36, 194, 312, 424, 627, 346}, - {5, 2, 61, 29, 45, 58, 80, 311, 1, 17, 209, 227, 52, 243, 106, 869, 454, 151, 592, 496, 48, 334, 14, 155, 6, 186, 46, 171, 75, 21, 255, 667}, - {244, 44, 110, 141, 260, 30, 269, 352, 839, 131, 574, 228, 373, 276, 1, 406, 219, 717, 217, 137, 253, 224, 120, 93, 36, 31, 567, 116, 661, 187, 341, 88}, - {12, 99, 79, 139, 11, 453, 196, 51, 277, 474, 111, 23, 542, 37, 94, 188, 33, 13, 401, 775, 40, 961, 313, 102, 4, 339, 153, 485, 629, 134, 300, 431}, - {16, 35, 9, 0, 68, 24, 149, 69, 67, 18, 1, 114, 65, 230, 71, 7, 103, 133, 50, 167, 212, 118, 101, 191, 140, 64, 399, 28, 124, 283, 55, 565}, - {88, 30, 274, 435, 131, 613, 190, 100, 93, 829, 166, 1, 187, 795, 530, 127, 382, 957, 960, 160, 31, 137, 466, 264, 39, 800, 406, 254, 28, 473, 521, 219}, - {167, 16, 18, 118, 212, 24, 60, 71, 101, 68, 191, 9, 375, 411, 363, 35, 0, 1, 589, 199, 302, 21, 447, 55, 146, 126, 92, 271, 647, 121, 562, 48}, - {64, 141, 86, 177, 77, 128, 147, 597, 304, 95, 269, 102, 275, 4, 352, 49, 120, 5, 372, 194, 465, 13, 588, 237, 947, 216, 202, 180, 612, 751, 107, 534}, - {18, 65, 90, 403, 523, 289, 240, 214, 194, 102, 701, 475, 202, 217, 283, 862, 389, 51, 33, 0, 494, 421, 453, 817, 84, 64, 847, 899, 352, 13, 23, 437}, - {13, 51, 23, 202, 5, 12, 21, 128, 15, 115, 0, 1, 141, 120, 64, 32, 4, 2, 515, 403, 165, 457, 3, 10, 700, 99, 453, 318, 719, 450, 308, 401}, - {98, 223, 393, 31, 1, 271, 834, 791, 167, 44, 202, 64, 93, 697, 5, 116, 77, 125, 450, 446, 212, 18, 541, 293, 51, 120, 195, 132, 284, 13, 807, 765}, - {15, 515, 700, 753, 4, 11, 23, 13, 40, 51, 82, 165, 0, 110, 93, 33, 141, 64, 120, 5, 10, 77, 3, 102, 180, 32, 202, 125, 8, 197, 31, 21}, - {15, 515, 700, 753, 0, 1, 13, 2, 901, 23, 5, 341, 3, 51, 82, 8, 4, 180, 961, 9, 115, 10, 12, 6, 898, 7, 351, 141, 134, 22, 31, 120}, - {234, 416, 77, 5, 315, 639, 325, 202, 147, 198, 113, 49, 450, 61, 455, 142, 0, 21, 22, 342, 329, 494, 178, 58, 102, 427, 318, 230, 13, 120, 43, 470}, - {60, 146, 16, 18, 156, 126, 121, 271, 199, 360, 132, 24, 167, 0, 640, 10, 71, 522, 21, 92, 5, 340, 107, 354, 118, 150, 22, 195, 446, 35, 28, 212}, - {4, 361, 11, 14, 56, 368, 377, 161, 27, 12, 300, 77, 59, 200, 17, 554, 202, 33, 40, 494, 495, 21, 210, 80, 757, 25, 128, 23, 19, 38, 444, 53}, - {141, 82, 217, 351, 15, 352, 120, 1, 180, 260, 515, 64, 854, 36, 700, 317, 752, 372, 13, 269, 77, 753, 922, 21, 349, 23, 202, 110, 93, 137, 51, 373}, - {15, 515, 700, 753, 77, 13, 0, 1, 23, 33, 102, 2, 51, 4, 3, 5, 291, 217, 10, 9, 450, 120, 341, 7, 317, 6, 11, 117, 115, 8, 260, 180}, - {15, 515, 120, 13, 700, 23, 77, 141, 1, 260, 0, 753, 180, 51, 137, 202, 115, 365, 110, 291, 217, 5, 128, 9, 21, 341, 197, 269, 2, 450, 317, 165}, - {174, 6, 348, 85, 138, 74, 280, 204, 66, 233, 192, 355, 289, 65, 81, 580, 636, 353, 25, 91, 104, 343, 673, 214, 64, 95, 42, 712, 792, 32, 194, 90}, - {152, 497, 452, 59, 4, 216, 11, 79, 94, 77, 128, 188, 269, 339, 588, 33, 76, 529, 318, 32, 141, 471, 12, 202, 111, 21, 5, 51, 37, 90, 72, 177}, - {417, 499, 10, 141, 253, 244, 110, 559, 8, 564, 180, 260, 728, 120, 352, 638, 642, 341, 951, 206, 143, 752, 901, 93, 137, 661, 922, 373, 44, 31, 811, 197}, - {13, 77, 23, 33, 4, 51, 0, 102, 128, 59, 141, 40, 64, 115, 177, 10, 137, 22, 202, 2, 7, 11, 90, 1, 117, 180, 269, 14, 49, 6, 134, 3}, - {1, 2, 22, 0, 36, 5, 67, 50, 14, 28, 12, 86, 38, 46, 83, 168, 194, 65, 103, 114, 49, 7, 10, 95, 21, 69, 23, 24, 128, 51, 55, 13}, - {17, 106, 119, 207, 255, 306, 742, 378, 84, 62, 136, 45, 3, 5, 240, 80, 61, 56, 209, 383, 311, 790, 655, 32, 2, 440, 76, 151, 58, 29, 179, 263}, - {3, 128, 1, 141, 2, 202, 33, 5, 64, 15, 0, 515, 102, 13, 269, 10, 700, 180, 134, 51, 120, 6, 77, 318, 23, 137, 17, 117, 753, 197, 82, 153}, - {514, 38, 377, 328, 11, 57, 41, 248, 880, 266, 556, 4, 152, 361, 471, 757, 485, 403, 305, 102, 3, 211, 313, 99, 457, 130, 12, 14, 157, 40, 23, 54}, - {68, 0, 167, 101, 9, 118, 264, 520, 16, 18, 21, 478, 562, 1, 124, 212, 100, 936, 664, 777, 191, 88, 806, 154, 48, 24, 759, 604, 35, 252, 265, 65}, - {230, 689, 699, 213, 466, 352, 217, 831, 30, 443, 418, 144, 854, 201, 840, 855, 1, 251, 203, 317, 530, 957, 96, 93, 822, 539, 36, 752, 351, 137, 83, 800}, - {33, 77, 102, 117, 15, 82, 13, 134, 23, 64, 0, 515, 120, 153, 51, 4, 40, 128, 700, 260, 202, 141, 196, 22, 753, 11, 351, 10, 1, 326, 95, 269}, - {11, 40, 33, 51, 117, 13, 542, 328, 14, 134, 38, 153, 23, 12, 485, 231, 102, 54, 775, 37, 3, 377, 111, 139, 211, 4, 457, 403, 369, 475, 99, 719}, - {33, 64, 77, 128, 141, 2, 1, 202, 102, 13, 23, 117, 0, 15, 3, 153, 51, 134, 10, 40, 6, 5, 515, 269, 137, 180, 318, 165, 700, 7, 196, 753}, - {15, 515, 700, 753, 4, 1, 5, 11, 13, 21, 33, 180, 93, 141, 64, 2, 23, 77, 82, 3, 0, 102, 32, 40, 352, 341, 10, 197, 98, 110, 117, 901}, - {1, 2, 14, 67, 50, 46, 38, 24, 103, 83, 0, 5, 36, 28, 29, 133, 114, 96, 65, 52, 18, 75, 54, 108, 22, 7, 238, 58, 160, 9, 361, 69}, - {258, 201, 276, 137, 160, 860, 116, 261, 295, 843, 567, 144, 131, 44, 187, 268, 943, 219, 284, 31, 202, 935, 141, 98, 662, 203, 127, 96, 36, 93, 224, 1}, - {7, 2, 14, 16, 46, 87, 75, 52, 92, 278, 29, 38, 140, 70, 1, 5, 35, 294, 24, 262, 135, 69, 171, 172, 58, 409, 112, 60, 50, 66, 97, 12}, - {13, 23, 0, 2, 51, 1, 33, 4, 115, 10, 15, 141, 77, 3, 5, 180, 217, 515, 9, 7, 64, 11, 700, 6, 102, 40, 197, 22, 317, 753, 165, 202}, - {74, 145, 6, 66, 25, 204, 42, 29, 222, 337, 138, 26, 7, 525, 192, 174, 746, 287, 544, 135, 415, 2, 609, 632, 112, 64, 87, 0, 85, 45, 712, 396}, - {77, 33, 102, 15, 217, 13, 23, 141, 202, 515, 51, 700, 291, 4, 269, 753, 317, 180, 21, 64, 318, 115, 128, 0, 275, 2, 352, 196, 3, 5, 137, 11}, - {187, 219, 258, 871, 44, 442, 160, 574, 137, 224, 908, 116, 839, 131, 36, 926, 276, 201, 93, 228, 202, 860, 31, 613, 144, 531, 406, 1, 902, 30, 190, 318}, - {1, 372, 141, 5, 21, 77, 225, 744, 96, 30, 23, 349, 13, 291, 269, 284, 69, 442, 459, 144, 303, 839, 217, 622, 160, 330, 260, 48, 120, 410, 189, 352}, - {66, 222, 2, 74, 29, 87, 135, 6, 7, 145, 52, 25, 294, 337, 226, 172, 138, 331, 42, 70, 97, 112, 26, 1, 632, 192, 43, 5, 415, 609, 461, 353}, - {45, 17, 106, 209, 5, 2, 21, 29, 48, 207, 3, 186, 243, 155, 255, 263, 454, 119, 400, 496, 270, 14, 290, 62, 425, 1, 171, 32, 659, 52, 38, 56}, - {93, 88, 141, 120, 30, 213, 260, 373, 100, 717, 459, 82, 110, 1, 166, 450, 180, 321, 217, 372, 36, 269, 131, 225, 22, 352, 326, 466, 473, 187, 244, 410}, - {266, 57, 152, 381, 313, 471, 12, 229, 99, 369, 339, 62, 157, 3, 4, 37, 77, 38, 188, 17, 11, 162, 40, 184, 129, 59, 475, 775, 128, 452, 403, 453}, - {217, 352, 317, 141, 752, 15, 180, 515, 372, 365, 700, 341, 753, 349, 77, 21, 291, 1, 115, 244, 64, 120, 13, 98, 269, 82, 5, 498, 864, 351, 23, 144}, - {14, 514, 369, 102, 403, 377, 51, 719, 880, 153, 23, 13, 457, 11, 485, 4, 401, 12, 328, 453, 33, 40, 117, 57, 629, 38, 730, 236, 134, 670, 361, 961}, - {107, 7, 172, 14, 92, 135, 2, 359, 60, 314, 46, 16, 126, 278, 232, 150, 279, 32, 38, 392, 298, 5, 35, 97, 24, 192, 259, 288, 330, 52, 356, 312}, - {0, 4, 25, 13, 59, 90, 65, 23, 26, 19, 18, 12, 5, 216, 91, 51, 389, 33, 77, 11, 22, 85, 27, 81, 21, 177, 746, 45, 42, 194, 37, 123}, - {5, 49, 315, 202, 416, 77, 455, 639, 450, 21, 197, 137, 350, 13, 408, 0, 329, 318, 494, 344, 61, 402, 64, 509, 347, 120, 113, 48, 95, 713, 308, 401}, - {130, 47, 381, 390, 59, 90, 200, 214, 289, 6, 65, 472, 29, 64, 874, 648, 50, 751, 624, 26, 52, 32, 4, 194, 875, 714, 85, 249, 247, 33, 881, 19}, - {51, 23, 453, 13, 719, 12, 457, 165, 37, 730, 99, 4, 386, 197, 401, 17, 11, 2, 3, 15, 5, 961, 475, 6, 515, 64, 54, 700, 32, 115, 0, 403}, - {15, 515, 1, 13, 700, 2, 23, 0, 753, 5, 3, 180, 51, 4, 165, 12, 141, 21, 197, 457, 7, 115, 6, 9, 352, 10, 120, 202, 8, 341, 11, 77}, - {0, 9, 1, 67, 35, 28, 68, 16, 24, 65, 18, 69, 50, 114, 103, 12, 22, 13, 5, 101, 2, 96, 23, 83, 149, 21, 39, 55, 7, 175, 433, 124}, - {28, 105, 22, 0, 1, 320, 170, 9, 49, 301, 109, 95, 127, 31, 98, 55, 65, 35, 2, 24, 168, 159, 36, 713, 16, 740, 13, 338, 21, 44, 512, 23}, - {13, 77, 4, 51, 23, 33, 102, 202, 128, 59, 40, 0, 64, 141, 117, 403, 115, 11, 15, 318, 153, 269, 22, 515, 475, 134, 10, 494, 177, 1, 90, 210}, - {13, 23, 0, 51, 77, 33, 2, 141, 4, 10, 1, 64, 115, 102, 3, 6, 22, 15, 217, 11, 180, 7, 40, 515, 165, 202, 177, 9, 269, 128, 700, 5}, - {456, 116, 492, 8, 949, 268, 867, 391, 203, 51, 499, 13, 719, 386, 31, 791, 457, 918, 125, 10, 23, 93, 479, 685, 417, 0, 22, 338, 506, 551, 870, 730}, - {17, 237, 45, 180, 106, 62, 32, 64, 115, 41, 136, 498, 255, 21, 197, 129, 241, 13, 3, 227, 23, 352, 165, 752, 350, 365, 449, 155, 4, 546, 476, 38}, - {1, 15, 180, 515, 0, 2, 341, 700, 901, 352, 4, 141, 13, 3, 752, 5, 753, 217, 317, 115, 365, 23, 197, 21, 51, 165, 31, 6, 269, 202, 77, 7}, - {205, 141, 216, 269, 497, 4, 588, 76, 59, 152, 128, 452, 79, 77, 875, 11, 72, 94, 188, 217, 352, 12, 247, 37, 90, 64, 32, 1, 474, 23, 947, 372}, - {64, 247, 217, 237, 317, 180, 752, 115, 349, 141, 498, 13, 437, 304, 23, 372, 352, 164, 579, 291, 33, 864, 177, 197, 0, 490, 72, 10, 482, 77, 269, 51}, - {2, 1, 0, 13, 15, 141, 3, 77, 5, 515, 64, 33, 23, 180, 6, 700, 4, 117, 217, 7, 10, 11, 102, 165, 753, 197, 115, 134, 40, 352, 12, 269}, - {11, 40, 38, 328, 33, 542, 12, 313, 41, 339, 23, 157, 377, 117, 369, 51, 471, 99, 775, 485, 13, 305, 457, 57, 14, 475, 37, 248, 4, 54, 188, 719}, - {33, 77, 102, 40, 13, 23, 0, 51, 4, 128, 64, 202, 117, 141, 22, 196, 153, 10, 134, 15, 59, 269, 1, 137, 65, 11, 403, 318, 453, 86, 515, 177}, - {472, 80, 34, 250, 495, 161, 17, 14, 469, 176, 128, 4, 389, 106, 283, 436, 216, 527, 3, 297, 483, 177, 53, 56, 231, 194, 119, 84, 719, 57, 255, 59}, - {317, 352, 180, 141, 217, 752, 115, 341, 365, 244, 1, 269, 202, 901, 253, 15, 21, 498, 372, 4, 137, 515, 13, 2, 700, 318, 5, 197, 23, 143, 753, 349}, - {9, 39, 101, 18, 265, 100, 333, 520, 252, 16, 0, 329, 593, 1, 553, 364, 68, 167, 310, 30, 121, 254, 118, 158, 363, 166, 60, 604, 272, 24, 286, 404}, - {15, 515, 1, 180, 700, 901, 0, 2, 753, 341, 752, 4, 3, 13, 115, 365, 317, 5, 23, 197, 141, 217, 165, 352, 6, 22, 36, 9, 137, 51, 7, 10}, - {131, 39, 9, 829, 166, 613, 578, 827, 1, 30, 716, 254, 100, 98, 31, 224, 0, 406, 228, 310, 616, 219, 44, 846, 127, 190, 938, 96, 265, 371, 856, 438}, - {17, 64, 62, 106, 141, 751, 136, 292, 32, 129, 352, 41, 38, 476, 86, 128, 214, 237, 5, 177, 123, 209, 217, 45, 269, 954, 162, 710, 180, 3, 90, 4}, - {25, 42, 235, 65, 650, 736, 605, 6, 630, 85, 123, 343, 233, 256, 26, 122, 63, 389, 141, 249, 416, 444, 368, 194, 19, 108, 138, 174, 90, 0, 544, 511}, - {184, 229, 152, 57, 266, 432, 497, 452, 17, 381, 619, 257, 313, 12, 4, 205, 59, 3, 99, 471, 157, 128, 5, 129, 339, 369, 77, 11, 32, 45, 202, 2}, - {137, 202, 160, 860, 141, 30, 93, 567, 36, 276, 295, 261, 131, 39, 9, 964, 201, 843, 1, 98, 800, 318, 116, 22, 943, 187, 10, 219, 206, 44, 269, 535}, - {0, 493, 125, 64, 49, 9, 279, 10, 35, 18, 93, 55, 293, 31, 14, 13, 194, 165, 325, 48, 22, 132, 21, 107, 98, 389, 44, 581, 342, 259, 174, 137}, - {15, 515, 700, 753, 4, 33, 13, 77, 23, 5, 51, 32, 102, 40, 93, 11, 349, 141, 21, 8, 82, 202, 64, 31, 110, 10, 117, 0, 1, 44, 3, 318}, - {110, 253, 854, 811, 352, 141, 244, 951, 180, 642, 661, 384, 498, 143, 752, 317, - 911, 10, 269, 206, 559, 351, 261, 120, 902, 533, 922, 959, 365, 160, 332, 217}, - {2, 29, 70, 1, 75, 52, 6, 220, 26, 112, 145, 331, 74, 163, 19, 69, 38, 324, 46, 58, 14, 5, 25, 21, 278, 223, 50, 307, 66, 7, 67, 409}, - {13, 23, 77, 33, 51, 4, 64, 141, 115, 102, 0, 2, 128, 177, 40, 11, 202, 10, 6, 180, 7, 15, 269, 1, 32, 217, 59, 22, 291, 3, 137, 515}, - {340, 897, 691, 478, 658, 264, 914, 382, 100, 812, 363, 1, 724, 156, 166, 698, 88, 521, 39, 404, 682, 447, 296, 96, 303, 411, 30, 909, 9, 274, 656, 772}, - {9, 18, 310, 101, 265, 159, 326, 120, 105, 158, 33, 363, 77, 195, 51, 55, 13, 39, 354, 132, 23, 7, 28, 639, 16, 137, 98, 1, 252, 272, 709, 49}, - {57, 313, 471, 12, 99, 369, 157, 339, 266, 152, 38, 37, 475, 453, 328, 775, 11, 40, 59, 188, 77, 514, 401, 403, 342, 4, 139, 33, 377, 51, 229, 14}, - {16, 7, 24, 14, 35, 140, 60, 92, 18, 69, 71, 2, 189, 1, 46, 230, 108, 388, 150, 38, 21, 172, 278, 67, 246, 267, 50, 309, 236, 135, 451, 0}, - {206, 417, 93, 940, 959, 473, 499, 203, 8, 137, 559, 728, 31, 202, 44, 120, 450, 141, 10, 260, 116, 564, 22, 326, 269, 318, 268, 244, 0, 1, 253, 638}, - {15, 515, 700, 753, 1, 0, 13, 2, 23, 4, 3, 51, 5, 217, 7, 77, 341, 115, 8, 9, 10, 33, 6, 180, 317, 349, 291, 120, 11, 165, 457, 901}, - {1, 2, 5, 14, 48, 21, 290, 32, 50, 45, 38, 46, 263, 207, 155, 72, 76, 29, 17, 408, 425, 171, 89, 52, 7, 0, 292, 449, 3, 227, 513, 428}, - {121, 132, 354, 167, 271, 223, 146, 98, 18, 463, 1, 668, 446, 195, 407, 60, 212, 447, 781, 48, 360, 363, 411, 522, 156, 393, 807, 9, 21, 16, 293, 13}, - {131, 578, 105, 371, 219, 224, 716, 616, 187, 49, 9, 254, 737, 159, 385, 98, 258, 127, 272, 761, 0, 916, 623, 910, 28, 286, 39, 31, 22, 518, 924, 242}, - {302, 467, 97, 6, 273, 1, 24, 484, 124, 51, 36, 18, 2, 398, 453, 421, 523, 69, 7, 23, 13, 403, 386, 150, 66, 0, 298, 65, 426, 165, 22, 158}, - {30, 190, 530, 88, 1, 100, 778, 539, 625, 274, 382, 410, 96, 731, 960, 39, 795, 321, 9, 131, 264, 144, 840, 748, 44, 166, 669, 957, 36, 31, 435, 228}, - {141, 1, 2, 128, 64, 33, 15, 202, 3, 0, 180, 5, 13, 77, 515, 134, 269, 102, 197, 700, 10, 137, 318, 6, 120, 165, 753, 352, 4, 82, 23, 117}, - {44, 201, 567, 116, 131, 224, 295, 662, 489, 268, 219, 31, 434, 144, 187, 276, 110, 384, 93, 261, 699, 137, 36, 442, 120, 1, 613, 30, 228, 64, 141, 244}, - {12, 15, 51, 23, 515, 37, 99, 13, 700, 0, 10, 117, 753, 38, 165, 82, 134, 120, 11, 453, 197, 64, 115, 569, 1, 629, 401, 22, 457, 474, 110, 153}, - {7, 135, 2, 92, 172, 14, 66, 140, 38, 52, 97, 46, 29, 74, 16, 324, 278, 226, 6, 87, 1, 571, 262, 5, 357, 232, 35, 380, 69, 314, 24, 330}, - {125, 386, 23, 963, 949, 60, 51, 391, 165, 221, 13, 197, 118, 21, 719, 193, 541, 421, 517, 150, 393, 7, 401, 453, 308, 5, 791, 551, 326, 558, 48, 173}, - {6, 85, 42, 25, 138, 222, 174, 235, 280, 256, 525, 289, 26, 214, 64, 746, 90, 32, 544, 65, 204, 19, 66, 337, 355, 95, 348, 415, 74, 29, 5, 312}, - {1, 14, 5, 50, 2, 67, 24, 0, 46, 69, 48, 21, 58, 103, 16, 12, 18, 38, 54, 96, 83, 7, 502, 45, 36, 181, 35, 9, 430, 28, 10, 155}, - {811, 351, 642, 180, 951, 752, 110, 638, 253, 10, 82, 352, 197, 341, 365, 564, 499, 854, 873, 55, 9, 417, 282, 901, 244, 22, 559, 143, 206, 141, 28, 898}, - {23, 13, 51, 15, 12, 453, 403, 165, 4, 515, 115, 719, 475, 457, 700, 523, 2, 21, 0, 99, 202, 197, 14, 5, 386, 753, 128, 401, 37, 308, 33, 117}, - {120, 13, 23, 77, 141, 1, 15, 93, 217, 82, 260, 51, 137, 202, 110, 515, 21, 180, 165, 5, 128, 102, 64, 351, 291, 700, 269, 352, 326, 203, 177, 0}, - {1, 5, 0, 22, 12, 2, 36, 21, 10, 23, 86, 13, 28, 51, 9, 128, 48, 14, 32, 50, 7, 3, 96, 137, 54, 4, 202, 49, 37, 65, 208, 323}, - {219, 98, 23, 127, 301, 51, 258, 308, 170, 910, 13, 165, 22, 105, 293, 616, 125, 242, 276, 401, 201, 395, 964, 115, 55, 284, 31, 374, 327, 206, 512, 900}, - {64, 180, 80, 165, 5, 237, 2, 250, 34, 58, 297, 61, 197, 17, 22, 29, 186, 498, 231, 445, 247, 3, 752, 311, 95, 32, 483, 153, 27, 45, 115, 469}, - {13, 77, 23, 33, 0, 2, 1, 64, 141, 51, 102, 10, 15, 3, 115, 40, 180, 6, 515, 128, 7, 22, 269, 202, 4, 217, 700, 5, 177, 117, 14, 165}, - {15, 120, 51, 515, 13, 450, 23, 700, 202, 153, 196, 753, 260, 64, 128, 141, 730, 4, 326, 386, 21, 523, 33, 318, 5, 457, 95, 32, 403, 1, 77, 269}, - {2, 1, 5, 29, 32, 45, 207, 263, 14, 425, 58, 72, 76, 21, 7, 408, 48, 46, 52, 186, 17, 292, 38, 6, 61, 89, 476, 50, 155, 720, 119, 3}, - {15, 515, 700, 753, 4, 13, 11, 5, 1, 23, 33, 21, 3, 141, 32, 2, 40, 180, 117, 64, 269, 202, 102, 197, 0, 165, 120, 51, 341, 352, 153, 12}, - {76, 5, 214, 129, 2, 123, 45, 710, 17, 249, 618, 460, 179, 32, 1, 257, 205, 519, 90, 207, 245, 184, 162, 61, 769, 209, 292, 106, 6, 29, 14, 128}, - {1, 15, 23, 13, 120, 141, 51, 515, 202, 21, 700, 165, 0, 180, 137, 2, 5, 77, 128, 93, 753, 260, 269, 197, 326, 33, 110, 352, 82, 102, 318, 48}, - {7, 2, 135, 14, 29, 87, 66, 52, 97, 172, 70, 112, 5, 58, 46, 337, 92, 16, 20, 43, 1, 38, 232, 155, 74, 294, 6, 461, 409, 151, 262, 32}, - {574, 187, 384, 926, 860, 110, 258, 434, 269, 531, 141, 244, 160, 261, 253, 116, - 699, 959, 940, 717, 533, 36, 219, 31, 902, 661, 871, 295, 201, 352, 10, 260}, - {156, 354, 296, 1, 182, 586, 64, 379, 340, 937, 850, 698, 31, 48, 98, 44, 120, 18, 163, 23, 30, 658, 195, 125, 77, 284, 223, 291, 774, 481, 96, 39}, - {250, 80, 34, 472, 17, 495, 176, 469, 33, 194, 64, 483, 4, 297, 141, 14, 161, 27, 53, 667, 56, 833, 73, 527, 585, 231, 106, 51, 84, 814, 2, 59}, - {97, 7, 81, 140, 66, 92, 172, 192, 24, 298, 43, 6, 74, 69, 314, 426, 462, 14, 501, 16, 21, 508, 60, 189, 267, 232, 230, 104, 48, 20, 135, 330}, - {31, 44, 116, 144, 268, 393, 492, 434, 367, 489, 127, 98, 918, 0, 384, 9, 22, 206, 948, 105, 93, 203, 1, 456, 332, 940, 299, 28, 137, 49, 293, 125}, - {15, 128, 33, 3, 13, 51, 141, 1, 202, 64, 23, 2, 515, 120, 102, 0, 5, 82, 10, 700, 165, 197, 269, 153, 403, 110, 753, 137, 196, 318, 117, 12}, - {31, 98, 127, 9, 0, 105, 22, 28, 44, 512, 293, 395, 299, 1, 242, 49, 685, 763, 320, 599, 125, 116, 109, 276, 284, 95, 870, 159, 23, 456, 36, 900}, - {7, 24, 124, 1, 6, 97, 2, 69, 14, 18, 23, 92, 21, 67, 66, 16, 5, 484, 43, 20, 118, 65, 36, 22, 28, 0, 51, 140, 13, 71, 29, 150}, - {1, 64, 442, 303, 284, 349, 202, 141, 622, 67, 154, 447, 260, 44, 652, 429, 9, 335, 237, 919, 197, 98, 167, 33, 682, 269, 547, 77, 863, 411, 340, 201}, - {1, 15, 2, 141, 515, 0, 700, 13, 3, 180, 10, 753, 5, 64, 77, 33, 4, 6, 7, 197, 102, 269, 165, 23, 134, 11, 352, 341, 291, 349, 22, 120}, - {99, 139, 12, 453, 196, 277, 775, 40, 475, 33, 23, 401, 215, 51, 11, 14, 77, 111, 313, 130, 38, 211, 37, 266, 129, 15, 339, 153, 719, 3, 369, 515}, - {33, 77, 102, 4, 23, 128, 13, 141, 202, 64, 51, 0, 40, 59, 269, 115, 117, 137, 153, 1, 318, 11, 10, 177, 15, 134, 22, 90, 196, 2, 403, 32}, - {7, 2, 14, 58, 70, 112, 16, 5, 87, 38, 46, 52, 6, 128, 135, 1, 32, 21, 155, 29, 66, 64, 0, 97, 92, 186, 172, 294, 13, 23, 20, 37}, - {15, 13, 515, 1, 700, 2, 23, 0, 753, 5, 3, 4, 51, 10, 341, 115, 365, 180, 11, 33, 317, 77, 6, 7, 217, 12, 197, 165, 117, 9, 64, 102}, - {2, 1, 14, 29, 75, 69, 67, 6, 52, 46, 38, 24, 103, 220, 83, 25, 70, 87, 262, 74, 96, 267, 50, 366, 26, 16, 226, 394, 357, 66, 108, 19}, - {9, 105, 18, 39, 1, 0, 16, 557, 101, 272, 252, 890, 326, 49, 265, 21, 137, 100, 23, 938, 13, 310, 159, 5, 31, 24, 254, 51, 30, 128, 202, 132}, - {80, 209, 45, 61, 667, 17, 6, 106, 5, 2, 151, 29, 483, 255, 454, 833, 27, 311, 112, 19, 738, 378, 1, 58, 113, 26, 25, 469, 119, 887, 32, 64}, - {13, 23, 51, 15, 5, 1, 515, 0, 21, 2, 12, 141, 700, 165, 202, 115, 753, 32, 180, 4, 3, 197, 10, 120, 457, 9, 269, 128, 64, 341, 7, 33}, - {99, 12, 453, 277, 139, 157, 369, 474, 339, 51, 38, 23, 37, 196, 188, 401, 775, 111, 11, 313, 328, 475, 153, 266, 4, 471, 79, 40, 33, 629, 102, 14}, - {7, 92, 16, 232, 97, 140, 126, 14, 60, 107, 66, 35, 298, 387, 314, 104, 246, 462, 441, 150, 0, 38, 24, 2, 172, 357, 230, 330, 5, 633, 22, 289}, - {13, 77, 23, 202, 318, 141, 33, 4, 51, 269, 102, 177, 115, 403, 137, 2, 40, 494, 90, 11, 342, 128, 31, 117, 21, 32, 7, 12, 64, 134, 14, 10}, - {13, 2, 0, 23, 141, 1, 77, 3, 180, 33, 6, 64, 15, 10, 115, 51, 4, 5, 217, 197, 7, 165, 515, 102, 22, 11, 700, 269, 40, 352, 177, 14}, - {15, 515, 700, 753, 4, 11, 1, 93, 13, 5, 180, 110, 82, 21, 120, 23, 2, 33, 10, 141, 3, 165, 197, 102, 901, 0, 32, 341, 117, 40, 153, 12}, - {15, 515, 700, 753, 1, 13, 0, 2, 23, 4, 77, 51, 3, 5, 341, 291, 7, 33, 6, 115, 10, 9, 8, 217, 11, 177, 120, 180, 102, 165, 197, 365}, - {20, 43, 198, 325, 173, 904, 104, 234, 66, 147, 77, 319, 416, 422, 97, 426, 5, 0, 7, 450, 861, 202, 712, 725, 2, 32, 639, 376, 38, 324, 945, 315}, - {105, 0, 9, 28, 49, 301, 170, 1, 127, 159, 22, 16, 31, 98, 512, 623, 24, 109, 158, 395, 35, 68, 371, 65, 713, 55, 2, 242, 293, 21, 44, 18}, - {213, 88, 689, 466, 230, 30, 321, 435, 699, 352, 217, 201, 795, 831, 144, 854, 1, 443, 96, 539, 530, 840, 418, 251, 855, 190, 93, 100, 669, 31, 957, 662}, - {130, 453, 47, 196, 4, 57, 14, 59, 236, 711, 51, 153, 730, 77, 412, 381, 23, 202, 108, 128, 361, 13, 283, 117, 11, 719, 200, 46, 34, 78, 210, 2}, - {1, 2, 5, 14, 0, 50, 36, 22, 38, 46, 65, 67, 12, 86, 114, 28, 103, 29, 208, 7, 10, 128, 21, 83, 218, 23, 96, 54, 194, 6, 133, 51}, - {6, 26, 74, 19, 165, 453, 14, 730, 1, 125, 197, 50, 29, 51, 138, 357, 13, 2, 108, 391, 70, 719, 46, 457, 47, 500, 386, 262, 112, 23, 235, 52}, - {9, 10, 376, 20, 43, 0, 49, 18, 30, 120, 2, 33, 325, 104, 501, 470, 77, 788, 725, 102, 523, 39, 858, 5, 904, 414, 174, 55, 137, 37, 342, 13}, - {15, 515, 700, 753, 0, 1, 13, 23, 51, 77, 120, 202, 341, 82, 5, 4, 9, 260, 2, 137, 141, 128, 115, 351, 901, 8, 180, 10, 197, 21, 450, 33}, - {105, 131, 272, 578, 9, 49, 371, 219, 159, 616, 286, 320, 224, 187, 716, 98, 28, 22, 0, 623, 127, 258, 910, 737, 385, 31, 239, 347, 254, 109, 424, 95}, - {457, 51, 13, 23, 961, 12, 719, 99, 453, 15, 4, 515, 165, 401, 629, 3, 700, 11, 17, 14, 2, 37, 753, 41, 57, 569, 38, 45, 0, 33, 5, 32}, - {202, 120, 5, 33, 318, 77, 450, 102, 1, 260, 403, 128, 494, 21, 165, 13, 269, 12, 326, 23, 342, 523, 402, 2, 817, 64, 15, 141, 125, 82, 457, 475}, - {141, 269, 352, 217, 180, 64, 349, 137, 202, 160, 317, 15, 372, 515, 700, 752, 318, 753, 244, 13, 437, 291, 165, 864, 22, 237, 5, 82, 954, 21, 77, 418}, - {70, 29, 2, 145, 74, 112, 26, 6, 75, 52, 19, 66, 632, 1, 87, 220, 5, 135, 163, 287, 307, 25, 226, 7, 58, 396, 294, 278, 113, 409, 69, 151}, - {82, 351, 317, 15, 752, 180, 898, 352, 141, 901, 515, 341, 10, 700, 365, 1, 753, 498, 0, 217, 253, 115, 55, 854, 33, 5, 143, 32, 21, 160, 36, 197}, - {39, 9, 310, 254, 0, 30, 101, 49, 252, 272, 100, 265, 105, 455, 159, 557, 190, 333, 286, 688, 18, 166, 1, 158, 709, 16, 625, 627, 31, 131, 327, 329}, - {2, 58, 29, 5, 1, 151, 186, 52, 70, 45, 7, 549, 14, 75, 112, 400, 113, 155, 61, 46, 227, 163, 311, 315, 66, 6, 307, 27, 17, 220, 287, 74}, - {141, 217, 13, 21, 352, 23, 269, 77, 180, 115, 317, 64, 202, 15, 349, 137, 5, 51, 165, 291, 318, 752, 372, 4, 0, 102, 33, 365, 197, 32, 341, 125}, - {68, 35, 0, 9, 65, 101, 149, 124, 24, 154, 175, 16, 28, 7, 67, 1, 18, 189, 114, 398, 55, 14, 345, 39, 118, 133, 69, 2, 230, 429, 71, 283}, - {66, 7, 29, 2, 112, 52, 20, 43, 97, 151, 74, 192, 135, 5, 173, 525, 337, 45, 145, 58, 415, 25, 14, 32, 644, 70, 544, 226, 222, 21, 6, 580}, - {31, 125, 44, 22, 116, 299, 242, 55, 1, 170, 64, 36, 479, 870, 456, 685, 10, 599, 558, 0, 268, 506, 28, 740, 23, 903, 492, 164, 393, 206, 2, 86}, - {188, 11, 79, 12, 99, 377, 94, 33, 542, 339, 40, 474, 111, 37, 4, 51, 102, 453, 139, 775, 13, 475, 23, 961, 277, 471, 134, 57, 431, 266, 115, 117}, - {658, 698, 340, 98, 296, 303, 1, 31, 850, 363, 156, 919, 44, 774, 586, 385, 120, 77, 82, 10, 223, 30, 354, 291, 23, 914, 478, 87, 260, 163, 48, 13}, - {15, 515, 700, 753, 82, 4, 1, 13, 901, 33, 197, 11, 5, 10, 23, 165, 2, 0, 180, 3, 21, 77, 51, 120, 365, 115, 217, 40, 117, 102, 32, 401}, - {15, 515, 700, 753, 4, 11, 5, 13, 1, 141, 3, 180, 23, 202, 21, 2, 269, 64, 165, 33, 40, 32, 0, 318, 120, 128, 12, 197, 117, 352, 51, 17}, - {91, 6, 233, 85, 370, 718, 81, 65, 25, 256, 63, 343, 42, 74, 235, 123, 138, 511, 397, 249, 26, 194, 650, 355, 64, 87, 544, 18, 90, 643, 66, 214}, - {23, 13, 202, 51, 21, 120, 1, 5, 141, 128, 450, 64, 318, 403, 15, 137, 260, 33, 12, 48, 32, 31, 125, 494, 269, 102, 165, 515, 77, 2, 197, 14}, - {180, 317, 365, 341, 752, 217, 115, 352, 901, 482, 372, 498, 1, 141, 15, 253, 515, 244, 2, 700, 0, 21, 13, 82, 23, 4, 579, 351, 753, 291, 269, 77}, - {13, 115, 197, 341, 9, 352, 468, 237, 64, 498, 23, 165, 22, 509, 901, 546, 482, 180, 28, 569, 317, 51, 365, 873, 391, 95, 86, 217, 49, 837, 752, 706}, - {13, 23, 51, 1, 141, 5, 165, 202, 21, 120, 64, 125, 180, 15, 2, 33, 197, 115, 128, 32, 260, 269, 12, 82, 4, 515, 137, 7, 318, 93, 0, 700}, - {214, 289, 90, 174, 874, 6, 138, 280, 65, 81, 64, 85, 355, 751, 194, 233, 312, 348, 835, 91, 0, 32, 343, 636, 249, 29, 875, 288, 519, 104, 247, 74}, - {15, 515, 700, 753, 4, 5, 11, 13, 1, 33, 23, 21, 2, 3, 102, 32, 141, 77, 180, 117, 31, 64, 0, 40, 134, 196, 120, 352, 12, 44, 197, 6}, - {33, 15, 13, 515, 117, 23, 700, 217, 134, 753, 0, 51, 153, 77, 141, 2, 4, 64, 196, 1, 3, 180, 10, 115, 5, 102, 6, 11, 22, 202, 165, 7}, - {15, 515, 700, 753, 33, 4, 77, 102, 1, 40, 13, 117, 11, 115, 134, 5, 21, 153, 23, 217, 3, 32, 2, 317, 120, 196, 180, 141, 51, 12, 59, 260}, - {15, 515, 700, 753, 13, 0, 1, 23, 2, 217, 51, 3, 4, 5, 8, 317, 115, 9, 341, 10, 202, 180, 6, 365, 7, 82, 457, 22, 120, 901, 33, 291}, - {7, 2, 135, 20, 97, 14, 66, 52, 337, 673, 192, 29, 43, 355, 353, 5, 16, 294, 107, 376, 147, 226, 331, 560, 64, 470, 222, 104, 415, 32, 4, 324}, - {195, 132, 142, 167, 146, 77, 363, 271, 121, 354, 202, 120, 647, 178, 786, 212, 687, 0, 101, 878, 16, 522, 60, 5, 450, 411, 35, 55, 98, 639, 259, 318}, - {202, 77, 20, 0, 318, 66, 104, 128, 102, 269, 177, 43, 33, 7, 216, 291, 494, 5, 2, 342, 74, 173, 97, 112, 450, 22, 337, 10, 234, 52, 64, 678}, - {107, 362, 612, 356, 359, 97, 414, 43, 259, 20, 392, 7, 298, 147, 819, 683, 465, 173, 729, 660, 319, 14, 5, 779, 581, 595, 246, 35, 501, 92, 0, 230}, - {6, 165, 14, 453, 13, 51, 19, 23, 386, 457, 74, 391, 308, 2, 26, 401, 47, 758, 603, 108, 719, 366, 1, 29, 309, 730, 324, 197, 133, 70, 115, 867}, - {179, 72, 205, 180, 247, 245, 4, 490, 352, 59, 317, 152, 79, 498, 94, 217, 148, 76, 752, 864, 11, 216, 141, 405, 89, 452, 197, 111, 497, 188, 37, 21}, - {107, 7, 298, 314, 14, 359, 32, 392, 232, 279, 172, 97, 60, 581, 387, 126, 121, 0, 534, 493, 356, 92, 441, 95, 13, 21, 35, 147, 22, 5, 16, 362}, - {156, 271, 354, 586, 360, 132, 591, 195, 121, 18, 340, 1, 5, 13, 21, 48, 668, 446, 23, 463, 296, 658, 60, 55, 407, 698, 146, 70, 626, 51, 163, 24}, - {13, 23, 51, 4, 0, 12, 457, 15, 11, 453, 2, 515, 5, 1, 99, 10, 115, 165, 700, 475, 401, 403, 3, 961, 40, 14, 37, 753, 719, 32, 64, 569}, - {48, 125, 21, 165, 13, 221, 23, 763, 423, 508, 197, 5, 98, 92, 193, 16, 441, 386, 64, 314, 293, 457, 391, 140, 49, 60, 102, 693, 683, 51, 35, 867}, - {202, 77, 120, 450, 5, 318, 1, 494, 0, 195, 18, 132, 523, 403, 326, 604, 354, 260, 121, 576, 203, 167, 234, 817, 682, 49, 35, 615, 21, 20, 13, 102}, - {39, 9, 166, 30, 0, 101, 158, 68, 404, 190, 333, 274, 252, 310, 88, 100, 49, 28, 344, 35, 21, 22, 419, 131, 438, 1, 16, 65, 530, 694, 124, 10}, - {15, 515, 700, 753, 110, 4, 1, 11, 165, 180, 93, 13, 82, 5, 2, 197, 33, 120, 0, 3, 10, 23, 21, 115, 901, 217, 341, 77, 317, 51, 32, 117}, - {2, 29, 1, 14, 6, 52, 5, 46, 50, 26, 70, 19, 103, 58, 38, 67, 96, 262, 516, 309, 218, 133, 108, 27, 75, 17, 112, 114, 24, 487, 331, 83}, - {120, 77, 15, 13, 1, 141, 260, 23, 515, 217, 110, 51, 137, 700, 317, 202, 165, 291, 180, 21, 753, 128, 0, 177, 326, 93, 450, 82, 64, 269, 197, 5}, - {255, 59, 554, 297, 183, 56, 33, 444, 108, 358, 123, 196, 269, 122, 77, 153, 57, 177, 117, 730, 19, 467, 605, 130, 128, 50, 275, 4, 291, 475, 134, 133}, - {13, 23, 51, 12, 153, 14, 117, 120, 165, 134, 99, 401, 38, 453, 15, 128, 197, 719, 64, 515, 475, 403, 37, 33, 196, 700, 40, 125, 5, 0, 54, 2}, - {64, 33, 174, 348, 95, 108, 467, 554, 56, 0, 25, 306, 233, 6, 63, 511, 343, 120, 13, 85, 29, 561, 543, 707, 319, 180, 899, 355, 77, 49, 256, 18}, - {120, 260, 51, 23, 77, 15, 202, 1, 93, 82, 141, 450, 13, 326, 515, 137, 21, 5, 64, 33, 110, 700, 128, 165, 318, 203, 269, 102, 351, 753, 197, 125}, - {15, 515, 700, 753, 4, 13, 11, 1, 5, 21, 23, 2, 33, 64, 3, 180, 32, 141, 22, 102, 77, 0, 10, 93, 82, 352, 117, 40, 341, 31, 165, 6}, - {15, 515, 700, 753, 341, 13, 23, 141, 33, 1, 0, 217, 4, 77, 180, 10, 82, 351, 51, 137, 5, 64, 9, 317, 21, 11, 102, 40, 260, 202, 854, 115}, - {105, 272, 131, 22, 327, 286, 28, 239, 320, 9, 109, 578, 219, 49, 98, 224, 95, 159, 538, 371, 616, 127, 187, 64, 713, 55, 0, 170, 168, 258, 716, 623}, - {16, 18, 68, 35, 24, 60, 71, 118, 92, 126, 0, 9, 101, 191, 7, 55, 154, 175, 212, 14, 167, 150, 302, 28, 375, 1, 107, 124, 346, 273, 21, 108}, - {20, 147, 43, 470, 376, 142, 904, 178, 427, 798, 0, 595, 198, 325, 858, 319, 61, 202, 173, 97, 5, 422, 14, 22, 107, 259, 32, 49, 887, 77, 414, 392}, - {13, 23, 51, 12, 33, 15, 99, 64, 128, 515, 453, 202, 117, 153, 37, 102, 700, 40, 134, 196, 120, 0, 2, 753, 141, 14, 38, 3, 82, 403, 77, 21}, - {383, 17, 62, 136, 84, 119, 56, 440, 3, 504, 240, 80, 378, 129, 123, 548, 106, 128, 4, 11, 14, 555, 162, 32, 184, 361, 59, 64, 205, 5, 469, 57}, - {70, 1, 48, 652, 5, 638, 846, 888, 21, 349, 269, 260, 340, 562, 767, 761, 163, 883, 774, 141, 125, 518, 591, 0, 23, 9, 87, 13, 371, 303, 622, 31}, - {66, 135, 6, 97, 74, 278, 69, 7, 14, 324, 267, 172, 2, 140, 462, 1, 357, 38, 808, 550, 92, 841, 189, 29, 16, 25, 298, 87, 75, 204, 24, 335}, - {51, 23, 33, 13, 102, 40, 12, 128, 64, 77, 10, 202, 0, 196, 117, 4, 14, 99, 134, 453, 65, 153, 11, 475, 139, 403, 22, 141, 86, 2, 21, 15}, - {88, 100, 264, 166, 274, 435, 772, 1, 382, 921, 96, 478, 30, 438, 639, 909, 897, 521, 190, 466, 960, 410, 9, 144, 530, 418, 31, 329, 265, 691, 778, 93}, - {62, 440, 136, 56, 84, 3, 504, 548, 555, 383, 4, 17, 129, 128, 507, 361, 123, 59, 119, 162, 14, 57, 152, 328, 161, 11, 202, 495, 184, 27, 80, 215}, - {911, 617, 332, 959, 206, 141, 253, 244, 282, 384, 110, 120, 10, 260, 352, 143, - 951, 811, 269, 373, 160, 417, 93, 531, 728, 203, 434, 940, 137, 55, 36, 717}, - {120, 15, 260, 141, 77, 1, 515, 82, 700, 351, 33, 23, 450, 13, 110, 326, 64, 217, 269, 753, 203, 137, 102, 5, 165, 21, 51, 291, 93, 177, 373, 128}, - {15, 515, 700, 753, 0, 1, 2, 23, 13, 51, 5, 9, 82, 901, 180, 8, 3, 4, 120, 6, 7, 141, 93, 12, 197, 341, 10, 33, 115, 730, 64, 125}, - {7, 104, 97, 107, 356, 232, 66, 560, 298, 289, 14, 707, 38, 568, 359, 64, 20, 0, 65, 324, 22, 214, 92, 32, 192, 5, 387, 43, 712, 90, 172, 95}, - {6, 1, 2, 66, 67, 14, 74, 24, 108, 29, 69, 83, 458, 7, 25, 38, 135, 103, 36, 150, 451, 114, 52, 594, 75, 65, 380, 18, 267, 602, 19, 278}, - {13, 23, 51, 12, 115, 21, 202, 5, 457, 15, 4, 1, 64, 719, 0, 403, 2, 3, 453, 165, 99, 141, 401, 128, 32, 515, 10, 37, 523, 197, 120, 700}, - {57, 59, 4, 11, 412, 381, 77, 53, 421, 291, 250, 368, 99, 14, 27, 369, 803, 283, 23, 108, 403, 19, 339, 210, 0, 401, 12, 444, 236, 40, 361, 736}, - {15, 515, 700, 1, 0, 753, 2, 13, 23, 5, 51, 180, 3, 115, 6, 7, 457, 4, 9, 8, 12, 82, 197, 165, 141, 901, 120, 719, 33, 64, 21, 22}, - {64, 95, 180, 247, 929, 146, 90, 126, 197, 32, 237, 60, 288, 165, 316, 92, 5, 13, 77, 7, 217, 955, 522, 22, 16, 314, 132, 4, 317, 10, 312, 86}, - {15, 1, 120, 13, 23, 515, 0, 51, 700, 180, 141, 2, 5, 202, 21, 260, 753, 165, 137, 33, 77, 110, 197, 128, 326, 7, 450, 4, 102, 9, 269, 12}, - {14, 2, 16, 46, 1, 7, 24, 69, 75, 35, 38, 50, 29, 220, 52, 140, 267, 67, 18, 54, 70, 309, 5, 60, 92, 189, 171, 87, 71, 163, 58, 0}, - {31, 98, 127, 44, 9, 299, 0, 276, 293, 284, 116, 49, 935, 599, 105, 22, 456, 201, 28, 1, 39, 125, 242, 137, 371, 144, 131, 492, 159, 272, 51, 395}, - {6, 27, 151, 53, 573, 445, 297, 113, 26, 73, 436, 19, 491, 250, 396, 315, 45, 112, 145, 58, 614, 881, 25, 34, 611, 200, 17, 80, 70, 5, 138, 631}, - {32, 693, 81, 788, 90, 804, 403, 56, 494, 21, 84, 397, 202, 65, 18, 77, 64, 681, 214, 725, 523, 784, 526, 33, 102, 825, 240, 0, 115, 241, 817, 91}, - {24, 7, 14, 2, 18, 16, 65, 0, 108, 149, 28, 69, 1, 71, 154, 36, 124, 35, 67, 140, 189, 429, 92, 68, 66, 22, 55, 118, 302, 150, 9, 6}, - {0, 68, 9, 35, 65, 101, 189, 212, 114, 67, 124, 69, 1, 154, 149, 39, 230, 64, 252, 16, 88, 702, 103, 100, 18, 336, 28, 329, 520, 83, 30, 755}, - {5, 2, 186, 29, 61, 45, 17, 1, 52, 48, 58, 171, 155, 227, 80, 209, 311, 21, 14, 46, 50, 106, 243, 513, 334, 502, 496, 38, 3, 6, 32, 592}, - {15, 515, 700, 753, 13, 1, 2, 0, 3, 4, 5, 23, 341, 11, 10, 33, 6, 51, 165, 117, 153, 7, 180, 12, 365, 901, 77, 569, 197, 115, 64, 9}, - {13, 15, 23, 515, 0, 51, 1, 700, 4, 2, 753, 10, 3, 5, 12, 77, 33, 961, 165, 457, 197, 11, 115, 9, 22, 102, 40, 403, 202, 21, 14, 59}, - {15, 515, 700, 753, 13, 0, 1, 23, 2, 33, 102, 5, 4, 10, 9, 3, 51, 115, 77, 7, 6, 341, 12, 11, 217, 40, 457, 196, 180, 165, 8, 523}, - {166, 39, 30, 274, 190, 100, 333, 438, 530, 310, 88, 252, 0, 9, 539, 265, 1, 656, 404, 101, 625, 131, 778, 254, 31, 455, 676, 329, 724, 158, 21, 23}, - {734, 148, 94, 308, 431, 115, 37, 89, 111, 413, 79, 468, 197, 629, 341, 474, 569, 12, 13, 873, 179, 401, 11, 4, 180, 23, 205, 72, 59, 365, 134, 51}, - {539, 228, 224, 219, 816, 190, 30, 258, 871, 840, 669, 93, 406, 530, 957, 187, 160, 531, 748, 137, 131, 88, 863, 36, 728, 839, 44, 213, 352, 116, 202, 466}, - {393, 791, 125, 801, 730, 551, 386, 23, 31, 175, 93, 98, 51, 13, 144, 788, 126, 203, 21, 345, 116, 22, 949, 110, 575, 165, 326, 44, 0, 4, 60, 221}, - {13, 23, 77, 141, 0, 4, 51, 2, 33, 115, 64, 1, 10, 3, 6, 15, 11, 102, 7, 217, 180, 40, 515, 22, 128, 177, 202, 9, 700, 269, 165, 5}, - {2, 29, 7, 70, 52, 14, 1, 58, 112, 46, 75, 5, 171, 163, 87, 220, 307, 151, 186, 334, 38, 66, 155, 16, 69, 135, 278, 45, 262, 97, 6, 21}, - {88, 321, 213, 100, 230, 435, 689, 466, 1, 382, 30, 352, 217, 699, 410, 96, 795, 36, 921, 752, 190, 141, 144, 180, 44, 831, 317, 83, 443, 31, 840, 251}, - {363, 411, 101, 520, 354, 9, 195, 668, 132, 156, 447, 1, 905, 364, 18, 23, 765, 664, 146, 5, 360, 13, 121, 96, 98, 31, 252, 39, 100, 759, 264, 551}, - {13, 23, 51, 730, 12, 719, 453, 457, 401, 475, 5, 21, 403, 2, 0, 1, 15, 4, 3, 899, 99, 32, 165, 11, 515, 308, 197, 115, 6, 961, 700, 523}, - {72, 76, 89, 12, 37, 4, 308, 179, 38, 528, 90, 431, 54, 205, 148, 184, 401, 57, 152, 474, 23, 59, 51, 245, 428, 11, 32, 99, 405, 316, 257, 21}, - {376, 20, 43, 147, 470, 173, 97, 595, 107, 319, 414, 142, 819, 5, 729, 178, 858, 7, 427, 32, 426, 104, 14, 0, 392, 362, 259, 61, 230, 77, 560, 246}, - {202, 141, 269, 494, 318, 137, 51, 128, 403, 4, 217, 96, 77, 5, 64, 177, 291, 180, 15, 352, 102, 10, 33, 349, 2, 317, 0, 341, 120, 515, 21, 453}, - {77, 202, 33, 128, 102, 318, 494, 269, 13, 0, 117, 23, 342, 291, 403, 15, 134, 51, 153, 141, 177, 515, 82, 137, 196, 700, 203, 64, 22, 351, 753, 4}, - {253, 110, 951, 352, 499, 811, 10, 854, 180, 638, 244, 559, 642, 752, 564, 8, 141, 143, 417, 341, 901, 260, 206, 197, 922, 661, 93, 15, 498, 373, 165, 911}, - {141, 13, 23, 180, 4, 217, 5, 1, 269, 317, 21, 0, 2, 202, 115, 51, 352, 77, 3, 197, 64, 341, 318, 15, 291, 9, 137, 93, 32, 165, 515, 33}, - {9, 0, 18, 252, 16, 101, 68, 39, 24, 118, 35, 109, 158, 329, 28, 167, 60, 364, 333, 265, 49, 100, 22, 419, 553, 55, 1, 677, 71, 7, 212, 159}, - {28, 109, 9, 39, 0, 158, 49, 22, 168, 35, 55, 175, 1, 65, 67, 185, 194, 159, 289, 95, 272, 114, 30, 105, 86, 584, 36, 169, 254, 2, 83, 24}, - {15, 515, 13, 700, 1, 753, 2, 23, 0, 3, 4, 5, 33, 341, 11, 51, 6, 10, 197, 115, 901, 180, 77, 40, 102, 12, 365, 165, 141, 217, 7, 317}, - {173, 693, 104, 422, 5, 18, 61, 32, 102, 0, 20, 13, 784, 560, 33, 66, 397, 526, 49, 207, 29, 25, 510, 707, 65, 6, 11, 344, 21, 263, 81, 77}, - {23, 13, 386, 51, 308, 801, 719, 221, 401, 949, 21, 730, 165, 421, 102, 115, 125, 33, 341, 670, 468, 117, 770, 1, 120, 6, 197, 14, 403, 97, 67, 958}, - {0, 49, 105, 16, 28, 24, 159, 9, 158, 320, 1, 68, 35, 239, 170, 18, 109, 7, 55, 65, 2, 95, 301, 124, 347, 14, 21, 154, 22, 127, 286, 31}, - {2, 5, 1, 207, 45, 29, 32, 58, 76, 61, 6, 263, 292, 655, 72, 14, 17, 476, 7, 119, 52, 306, 70, 64, 21, 90, 186, 214, 106, 38, 3, 790}, - {21, 6, 125, 49, 13, 64, 715, 66, 115, 95, 197, 33, 22, 32, 204, 165, 56, 278, 0, 408, 241, 120, 4, 808, 681, 350, 263, 85, 81, 571, 135, 509}, - {612, 427, 325, 107, 202, 5, 376, 49, 64, 392, 403, 470, 21, 147, 31, 788, 494, 14, 362, 465, 858, 98, 20, 804, 518, 43, 845, 318, 125, 97, 725, 534}, - {32, 21, 76, 72, 2, 1, 14, 5, 241, 449, 89, 38, 350, 221, 155, 48, 50, 292, 37, 46, 45, 90, 270, 54, 17, 179, 214, 12, 148, 430, 476, 413}, - {24, 0, 28, 16, 7, 124, 35, 154, 14, 149, 65, 18, 9, 68, 55, 108, 175, 71, 2, 1, 22, 109, 92, 67, 484, 336, 118, 69, 302, 398, 570, 420}, - {1, 5, 14, 2, 48, 50, 38, 67, 46, 21, 0, 54, 45, 270, 281, 12, 24, 32, 155, 96, 513, 103, 290, 83, 61, 58, 36, 17, 37, 72, 69, 181}, - {13, 961, 569, 197, 37, 15, 23, 474, 515, 94, 148, 111, 12, 165, 629, 341, 700, 79, 901, 401, 51, 405, 753, 10, 134, 4, 115, 734, 873, 11, 89, 117}, - {33, 23, 102, 51, 13, 40, 77, 128, 64, 202, 141, 15, 4, 12, 0, 1, 2, 117, 22, 11, 10, 403, 153, 515, 99, 318, 137, 269, 139, 196, 700, 134}, - {0, 1, 24, 67, 9, 16, 18, 35, 28, 69, 103, 50, 5, 2, 65, 12, 83, 68, 7, 96, 14, 22, 21, 149, 75, 114, 13, 133, 23, 71, 218, 54}, - {384, 617, 940, 332, 855, 911, 206, 959, 434, 282, 141, 10, 93, 253, 244, 110, 144, 268, 120, 36, 352, 137, 417, 203, 116, 31, 44, 269, 160, 201, 143, 951}, - {30, 93, 473, 137, 31, 704, 450, 652, 190, 203, 800, 254, 166, 274, 326, 144, 269, 160, 127, 303, 120, 625, 88, 848, 110, 435, 77, 521, 349, 131, 340, 744}, - {53, 27, 73, 26, 19, 250, 297, 200, 25, 630, 17, 6, 611, 122, 34, 42, 714, 235, 472, 65, 436, 14, 80, 684, 690, 106, 45, 113, 680, 108, 64, 4}, - {15, 515, 1, 2, 700, 0, 753, 3, 5, 141, 180, 4, 13, 77, 33, 10, 217, 6, 7, 134, 11, 352, 197, 64, 165, 341, 317, 23, 12, 115, 102, 40}, - {254, 530, 39, 613, 688, 221, 30, 31, 438, 190, 228, 960, 1, 44, 141, 21, 180, 406, 23, 166, 9, 202, 13, 96, 137, 48, 131, 829, 317, 269, 393, 51}, - {9, 39, 28, 35, 30, 166, 158, 36, 0, 175, 101, 346, 364, 67, 49, 68, 168, 420, 88, 1, 194, 131, 100, 352, 55, 83, 190, 64, 137, 570, 86, 65}, - {62, 56, 3, 548, 555, 507, 440, 161, 34, 4, 215, 136, 162, 514, 361, 527, 17, 14, 211, 130, 328, 11, 383, 123, 84, 183, 38, 57, 184, 152, 205, 494}, - {92, 126, 107, 7, 356, 493, 97, 279, 359, 298, 16, 246, 35, 60, 14, 441, 362, 121, 43, 423, 5, 132, 392, 20, 508, 230, 199, 146, 232, 173, 150, 414}, - {15, 82, 141, 515, 291, 922, 349, 700, 217, 260, 372, 120, 351, 93, 77, 753, 318, 352, 373, 854, 1, 326, 269, 21, 13, 102, 144, 202, 64, 23, 203, 137}, - {141, 217, 352, 115, 180, 13, 269, 317, 752, 77, 23, 21, 341, 197, 5, 372, 244, 291, 9, 64, 51, 102, 4, 1, 365, 2, 165, 33, 3, 48, 237, 351}, - {78, 47, 390, 19, 130, 453, 108, 27, 711, 813, 730, 444, 412, 283, 196, 690, 123, 14, 128, 26, 250, 389, 650, 236, 200, 65, 51, 4, 34, 183, 297, 73}, - {34, 250, 297, 80, 472, 64, 495, 17, 311, 3, 148, 45, 667, 61, 176, 53, 243, 27, 90, 161, 469, 141, 483, 151, 62, 128, 29, 4, 58, 56, 5, 231}, - {51, 23, 33, 13, 551, 77, 102, 326, 421, 21, 523, 120, 5, 899, 453, 692, 202, 153, 308, 615, 115, 958, 450, 401, 791, 68, 221, 93, 475, 18, 403, 4}, - {98, 223, 393, 363, 411, 1, 478, 834, 664, 156, 284, 691, 447, 791, 914, 293, 354, 724, 697, 9, 807, 541, 759, 51, 18, 421, 48, 264, 948, 586, 195, 848}, - {7, 14, 107, 232, 16, 92, 2, 60, 46, 5, 359, 121, 24, 526, 220, 620, 135, 1, 172, 21, 126, 314, 132, 77, 18, 75, 32, 278, 12, 23, 52, 38}, - {32, 76, 2, 1, 21, 72, 241, 14, 5, 48, 292, 89, 476, 45, 720, 270, 179, 90, 17, 214, 148, 38, 50, 29, 129, 155, 350, 46, 290, 227, 123, 464}, - {15, 515, 700, 753, 13, 23, 33, 77, 51, 4, 102, 0, 32, 202, 1, 11, 128, 82, 117, 141, 40, 5, 110, 8, 3, 90, 137, 21, 10, 318, 403, 165}, - {66, 6, 69, 2, 1, 74, 14, 135, 278, 267, 380, 24, 29, 97, 67, 38, 103, 75, 7, 388, 324, 25, 52, 150, 87, 83, 189, 357, 335, 108, 204, 172}, - {152, 4, 339, 59, 79, 471, 188, 11, 77, 94, 128, 33, 529, 377, 12, 111, 102, 202, 452, 402, 216, 99, 13, 542, 51, 40, 474, 37, 64, 291, 23, 961}, - {15, 515, 700, 753, 1, 0, 196, 13, 33, 2, 77, 5, 23, 102, 3, 10, 9, 7, 217, 4, 6, 153, 117, 177, 14, 457, 115, 12, 40, 730, 11, 134}, - {17, 209, 45, 106, 207, 5, 255, 119, 62, 2, 61, 3, 263, 742, 306, 655, 425, 378, 32, 56, 29, 136, 84, 80, 311, 58, 186, 240, 243, 383, 14, 21}, - {120, 260, 450, 15, 1, 23, 817, 13, 515, 523, 326, 5, 700, 51, 82, 31, 202, 64, 21, 753, 318, 93, 32, 269, 98, 33, 351, 77, 102, 125, 457, 165}, - {116, 492, 268, 93, 23, 206, 203, 0, 551, 918, 13, 51, 8, 22, 417, 940, 120, 10, 499, 31, 949, 791, 125, 523, 165, 473, 341, 730, 421, 959, 401, 391}, - {15, 515, 700, 753, 165, 13, 0, 1, 197, 23, 4, 82, 120, 2, 180, 12, 260, 719, 8, 3, 386, 117, 5, 523, 901, 11, 341, 51, 10, 9, 141, 351}, - {14, 24, 69, 7, 2, 66, 108, 1, 67, 6, 36, 398, 18, 267, 150, 97, 29, 38, 83, 149, 65, 74, 28, 0, 189, 71, 388, 16, 273, 124, 46, 22}, - {330, 96, 523, 335, 367, 662, 141, 839, 1, 922, 372, 615, 244, 717, 269, 443, 418, 352, 403, 692, 217, 854, 752, 180, 36, 64, 498, 576, 349, 201, 98, 284}, - {184, 90, 257, 205, 245, 229, 57, 152, 769, 17, 524, 5, 32, 497, 45, 432, 619, 2, 452, 266, 4, 106, 1, 21, 179, 59, 76, 3, 460, 292, 381, 128}, - {7, 14, 16, 2, 46, 5, 70, 107, 87, 13, 58, 307, 92, 32, 38, 23, 202, 0, 172, 24, 18, 21, 60, 128, 77, 35, 20, 10, 9, 4, 171, 112}, - {7, 66, 140, 16, 14, 92, 97, 69, 267, 172, 189, 24, 380, 2, 35, 60, 298, 451, 230, 135, 314, 74, 150, 71, 38, 357, 6, 330, 67, 423, 21, 443}, - {121, 167, 354, 132, 18, 446, 147, 101, 212, 146, 407, 16, 55, 35, 647, 191, 20, 271, 199, 68, 60, 259, 463, 107, 9, 126, 363, 7, 195, 43, 14, 411}, - {76, 90, 179, 32, 205, 21, 184, 460, 257, 288, 45, 245, 316, 5, 57, 152, 241, 2, 358, 1, 229, 72, 524, 148, 48, 769, 17, 4, 12, 38, 14, 720}, - {147, 259, 178, 878, 427, 465, 581, 198, 786, 798, 142, 534, 325, 929, 20, 362, 35, 132, 107, 376, 43, 5, 279, 77, 49, 146, 70, 202, 590, 771, 33, 14}, - {473, 93, 450, 778, 141, 30, 855, 466, 144, 203, 330, 530, 88, 523, 459, 372, 201, 617, 839, 704, 254, 321, 934, 326, 39, 36, 82, 717, 332, 213, 559, 403}, - {523, 475, 51, 899, 730, 453, 23, 719, 403, 33, 457, 13, 421, 386, 4, 120, 117, 196, 102, 153, 15, 801, 450, 817, 515, 260, 202, 11, 700, 99, 165, 125}, - {15, 1, 13, 515, 0, 2, 700, 5, 23, 753, 4, 3, 341, 317, 10, 115, 180, 11, 33, 64, 217, 77, 117, 165, 197, 7, 6, 365, 9, 141, 102, 134}, - {19, 4, 119, 40, 33, 202, 27, 84, 102, 56, 77, 73, 504, 485, 26, 494, 757, 63, 862, 59, 23, 300, 25, 12, 128, 11, 5, 13, 342, 880, 469, 6}, - {32, 20, 2, 13, 5, 21, 23, 6, 12, 38, 43, 29, 64, 7, 95, 51, 61, 207, 48, 147, 90, 178, 17, 182, 49, 0, 115, 202, 52, 362, 37, 22}, - {339, 188, 11, 79, 4, 94, 377, 12, 99, 111, 542, 102, 37, 33, 474, 51, 471, 40, 453, 152, 77, 13, 59, 403, 342, 23, 117, 57, 475, 134, 128, 38}, - {34, 128, 283, 176, 495, 231, 318, 432, 503, 275, 529, 527, 161, 53, 3, 202, 56, 291, 585, 469, 73, 17, 14, 412, 57, 27, 80, 245, 250, 381, 402, 51}, - {15, 515, 13, 700, 1, 217, 141, 120, 23, 180, 753, 115, 365, 51, 317, 341, 77, 260, 0, 291, 110, 137, 202, 5, 21, 269, 64, 36, 349, 2, 4, 10}, - {13, 15, 961, 515, 700, 753, 4, 12, 2, 457, 3, 11, 197, 51, 37, 569, 115, 23, 5, 0, 99, 10, 1, 134, 6, 111, 165, 33, 72, 40, 38, 79}, - {15, 515, 700, 753, 13, 1, 0, 2, 23, 33, 5, 3, 10, 4, 9, 115, 7, 102, 6, 51, 12, 217, 77, 11, 40, 457, 569, 341, 117, 317, 14, 719}, - {5, 76, 2, 32, 292, 214, 45, 1, 129, 519, 123, 179, 90, 710, 17, 29, 460, 72, 14, 207, 21, 249, 58, 205, 464, 263, 618, 48, 6, 245, 3, 257}, - {72, 76, 32, 4, 21, 12, 38, 23, 99, 54, 89, 3, 14, 17, 51, 57, 11, 90, 13, 488, 179, 2, 59, 148, 45, 37, 5, 115, 401, 1, 10, 421}, - {98, 223, 393, 1, 834, 264, 284, 791, 724, 293, 478, 772, 697, 909, 363, 682, 905, 447, 541, 821, 411, 51, 421, 9, 807, 48, 765, 31, 730, 96, 386, 410}, - {341, 13, 509, 8, 23, 638, 165, 901, 762, 10, 569, 242, 391, 197, 873, 642, 506, 499, 629, 961, 15, 180, 116, 456, 206, 546, 417, 1, 338, 457, 515, 867}, - {1, 2, 5, 50, 14, 38, 46, 114, 0, 36, 29, 22, 218, 65, 86, 96, 137, 21, 133, 285, 12, 10, 323, 181, 17, 58, 51, 23, 67, 7, 28, 6}, - {481, 878, 202, 13, 5, 23, 182, 32, 269, 21, 1, 318, 77, 142, 557, 494, 141, 33, 640, 137, 70, 291, 2, 51, 260, 415, 929, 403, 120, 58, 4, 259}, - {15, 515, 700, 753, 1, 4, 13, 0, 2, 5, 341, 3, 11, 180, 134, 12, 10, 317, 197, 365, 33, 21, 23, 165, 117, 6, 77, 7, 217, 37, 32, 498}, - {25, 119, 19, 6, 26, 42, 27, 17, 4, 790, 45, 814, 2, 469, 483, 84, 122, 1, 0, 33, 32, 128, 76, 80, 611, 113, 73, 56, 5, 240, 202, 77}, - {14, 2, 7, 1, 24, 0, 65, 6, 16, 69, 67, 22, 124, 28, 108, 5, 18, 36, 86, 10, 38, 46, 66, 398, 289, 168, 12, 83, 21, 23, 610, 13}, - {51, 23, 128, 13, 15, 202, 12, 120, 33, 64, 141, 82, 10, 515, 0, 403, 700, 3, 1, 99, 117, 269, 153, 165, 753, 5, 318, 197, 102, 260, 2, 137}, - {16, 35, 24, 0, 9, 18, 7, 1, 68, 69, 50, 71, 103, 65, 67, 189, 133, 23, 28, 13, 60, 537, 149, 335, 75, 21, 64, 5, 114, 2, 12, 14}, - {754, 803, 133, 576, 880, 543, 2, 1, 657, 50, 14, 38, 46, 5, 29, 67, 218, 36, 58, 171, 52, 96, 24, 103, 775, 0, 114, 83, 181, 54, 65, 45}, - {21, 32, 5, 3, 2, 17, 14, 72, 76, 1, 12, 23, 38, 51, 4, 54, 10, 0, 89, 13, 99, 137, 45, 36, 421, 115, 543, 11, 22, 128, 221, 48}, - {434, 384, 268, 144, 855, 940, 617, 206, 332, 116, 93, 911, 959, 282, 203, 137, 141, 489, 44, 120, 10, 110, 244, 36, 98, 31, 269, 253, 367, 417, 160, 9}, - {15, 2, 1, 0, 13, 515, 5, 700, 3, 23, 180, 217, 141, 10, 753, 4, 117, 6, 77, 33, 64, 7, 11, 197, 352, 317, 341, 134, 165, 115, 12, 9}, - {2, 113, 6, 25, 1, 0, 29, 4, 7, 833, 5, 45, 32, 61, 128, 19, 77, 151, 74, 145, 64, 42, 14, 210, 655, 106, 59, 177, 27, 17, 21, 738}, - {116, 268, 918, 203, 551, 31, 8, 692, 206, 791, 403, 499, 417, 93, 940, 421, 0, 23, 22, 120, 13, 523, 44, 51, 299, 473, 959, 1, 10, 475, 202, 125}, - {107, 126, 132, 612, 362, 279, 20, 146, 259, 493, 199, 121, 590, 43, 660, 147, 35, 376, 939, 60, 941, 534, 683, 5, 0, 953, 16, 7, 49, 649, 595, 470}, - {15, 515, 700, 753, 13, 1, 0, 23, 2, 33, 77, 4, 3, 51, 5, 102, 115, 10, 9, 341, 6, 7, 11, 342, 217, 12, 120, 180, 40, 317, 141, 8}, - {53, 27, 17, 161, 469, 378, 73, 527, 19, 136, 383, 250, 495, 56, 862, 26, 62, 84, 80, 106, 200, 4, 34, 14, 440, 297, 3, 128, 585, 5, 129, 123}, - {17, 45, 209, 106, 5, 207, 243, 454, 119, 255, 2, 263, 186, 290, 29, 3, 21, 62, 425, 61, 84, 32, 58, 56, 48, 408, 655, 136, 306, 14, 742, 227}, - {4, 152, 59, 452, 128, 79, 216, 11, 339, 471, 529, 188, 94, 77, 202, 12, 291, 33, 318, 377, 99, 51, 23, 5, 402, 349, 32, 474, 102, 13, 205, 111}, - {15, 515, 700, 753, 1, 0, 2, 13, 3, 5, 23, 4, 180, 51, 115, 9, 6, 12, 7, 8, 197, 33, 10, 961, 901, 77, 141, 752, 110, 22, 120, 341}, - {951, 752, 638, 811, 351, 642, 180, 253, 10, 341, 197, 901, 110, 873, 8, 244, 15, 352, 165, 898, 143, 515, 564, 762, 499, 55, 365, 700, 82, 753, 141, 854}, - {6, 262, 197, 350, 74, 26, 115, 509, 841, 583, 165, 38, 21, 13, 47, 50, 235, 19, 33, 324, 453, 4, 308, 196, 138, 99, 64, 903, 675, 1, 223, 130}, - {125, 165, 391, 23, 386, 221, 21, 13, 558, 457, 51, 867, 197, 115, 401, 758, 77, 97, 308, 791, 7, 180, 48, 120, 963, 451, 743, 89, 603, 134, 403, 450}, - {1, 14, 2, 5, 16, 46, 7, 38, 58, 24, 50, 0, 69, 48, 35, 67, 54, 18, 12, 75, 21, 45, 513, 155, 430, 37, 270, 9, 61, 163, 223, 32}, - {23, 13, 51, 0, 12, 15, 4, 1, 115, 2, 515, 453, 10, 457, 5, 3, 202, 21, 165, 700, 403, 11, 37, 64, 77, 401, 9, 197, 753, 59, 475, 99}, - {129, 84, 17, 56, 27, 495, 19, 548, 80, 123, 162, 378, 3, 504, 161, 469, 618, 73, 40, 53, 4, 26, 205, 184, 106, 183, 62, 6, 257, 128, 862, 12}, - {28, 9, 22, 49, 109, 1, 67, 0, 39, 55, 168, 158, 83, 36, 35, 86, 420, 194, 185, 159, 95, 105, 69, 208, 272, 103, 50, 114, 2, 254, 169, 30}, - {242, 391, 8, 456, 116, 13, 23, 492, 341, 165, 867, 51, 499, 457, 479, 638, 338, 509, 719, 10, 1, 642, 417, 762, 401, 93, 206, 268, 901, 569, 22, 197}, - {211, 162, 248, 130, 57, 4, 41, 556, 507, 266, 183, 152, 305, 361, 11, 129, 62, 229, 38, 471, 514, 313, 157, 300, 377, 3, 440, 128, 123, 328, 339, 59}, - {7, 92, 97, 16, 298, 140, 60, 126, 14, 35, 279, 314, 232, 246, 43, 230, 508, 173, 71, 107, 423, 24, 150, 779, 20, 189, 66, 18, 607, 21, 0, 653}, - {15, 515, 700, 753, 1, 0, 2, 13, 23, 5, 3, 180, 51, 901, 6, 4, 7, 12, 9, 115, 8, 457, 165, 82, 120, 197, 10, 64, 141, 341, 22, 117}, - {0, 18, 403, 25, 523, 74, 6, 24, 42, 91, 22, 102, 13, 51, 49, 193, 475, 681, 95, 85, 730, 64, 899, 397, 273, 750, 247, 673, 32, 805, 757, 288}, - {56, 0, 18, 65, 33, 554, 84, 343, 64, 6, 90, 561, 22, 19, 899, 108, 27, 63, 289, 475, 240, 467, 370, 32, 233, 214, 24, 123, 95, 287, 28, 194}, - {31, 98, 127, 9, 0, 44, 293, 105, 395, 299, 49, 242, 28, 22, 599, 116, 1, 284, 276, 125, 456, 685, 763, 159, 272, 623, 23, 935, 393, 144, 201, 137}, - {1, 5, 2, 14, 38, 46, 50, 48, 21, 7, 58, 45, 270, 61, 155, 171, 0, 290, 69, 32, 29, 54, 67, 16, 24, 666, 663, 17, 37, 75, 502, 52}, - {23, 51, 13, 453, 457, 12, 719, 4, 15, 99, 401, 2, 961, 3, 11, 730, 475, 515, 0, 1, 165, 115, 629, 700, 14, 17, 403, 40, 5, 33, 37, 64}, - {968, 967, 966, 965, 964, 963, 962, 961, 960, 959, 958, 957, 956, 955, 954, 953, - 952, 951, 950, 949, 948, 947, 946, 945, 944, 943, 942, 941, 940, 939, 938, 937}, - {2, 1, 14, 29, 67, 103, 6, 46, 52, 75, 24, 133, 38, 218, 83, 309, 36, 108, 70, 114, 96, 5, 238, 74, 25, 26, 220, 236, 65, 50, 69, 87}, - {7, 71, 16, 92, 24, 60, 14, 97, 150, 140, 35, 189, 149, 298, 18, 230, 43, 508, 2, 423, 69, 0, 38, 314, 66, 279, 399, 517, 251, 20, 232, 273}, - {23, 1, 120, 51, 13, 202, 77, 141, 260, 21, 15, 5, 128, 82, 2, 450, 269, 165, 102, 318, 48, 32, 137, 515, 125, 64, 12, 115, 351, 180, 33, 7}, - {77, 13, 33, 23, 64, 51, 4, 102, 141, 128, 40, 1, 2, 202, 0, 6, 177, 115, 137, 15, 59, 10, 11, 7, 269, 22, 515, 180, 318, 3, 700, 95}, - {101, 9, 18, 363, 264, 520, 411, 604, 676, 682, 905, 271, 16, 821, 167, 0, 621, 364, 39, 100, 121, 118, 166, 781, 647, 252, 1, 848, 447, 265, 404, 60}, - {144, 203, 326, 382, 166, 418, 93, 88, 96, 822, 1, 141, 859, 77, 744, 438, 110, 269, 921, 367, 521, 274, 100, 39, 494, 120, 403, 473, 217, 576, 13, 291}, - {13, 21, 180, 125, 5, 23, 191, 32, 18, 16, 146, 199, 115, 24, 165, 118, 0, 225, 22, 1, 60, 197, 64, 901, 375, 241, 48, 12, 408, 71, 522, 818}, - {15, 515, 700, 753, 13, 0, 23, 8, 1, 51, 82, 102, 2, 33, 4, 9, 180, 165, 5, 77, 10, 110, 12, 197, 120, 260, 18, 326, 351, 403, 22, 457}, - {33, 77, 102, 64, 13, 23, 128, 51, 141, 202, 1, 40, 0, 2, 117, 10, 15, 4, 6, 318, 269, 134, 22, 515, 180, 115, 177, 153, 137, 196, 3, 700}, - {174, 544, 104, 525, 74, 0, 151, 25, 6, 624, 29, 66, 2, 636, 81, 45, 204, 177, 64, 416, 7, 644, 5, 138, 222, 319, 355, 77, 22, 122, 789, 216}, - {141, 304, 372, 352, 291, 947, 177, 269, 128, 954, 77, 349, 217, 202, 64, 318, 498, 437, 102, 864, 86, 13, 115, 180, 137, 5, 210, 197, 32, 950, 678, 7}, - {161, 200, 53, 17, 714, 27, 34, 73, 472, 62, 585, 56, 440, 383, 136, 78, 527, 19, 4, 3, 106, 361, 14, 250, 80, 514, 377, 84, 322, 390, 862, 548}, - {32, 76, 72, 21, 38, 14, 89, 54, 12, 37, 2, 241, 5, 428, 17, 1, 181, 221, 350, 45, 3, 4, 449, 90, 148, 179, 99, 292, 794, 770, 477, 46}, - {33, 23, 128, 64, 141, 13, 77, 51, 102, 202, 2, 15, 1, 3, 40, 10, 5, 153, 269, 515, 165, 0, 117, 196, 180, 318, 6, 700, 137, 134, 120, 22}, - {96, 137, 30, 0, 9, 39, 840, 202, 669, 406, 141, 530, 613, 1, 180, 88, 22, 160, 679, 576, 28, 403, 31, 219, 49, 228, 829, 100, 36, 15, 10, 856}, - {180, 141, 352, 1, 15, 752, 115, 0, 217, 365, 2, 515, 13, 901, 341, 317, 23, 4, 197, 700, 269, 5, 3, 31, 753, 244, 21, 165, 253, 202, 51, 44}, - {1, 2, 67, 0, 28, 50, 83, 65, 14, 46, 103, 114, 24, 38, 36, 9, 69, 5, 18, 7, 22, 133, 55, 218, 16, 124, 29, 54, 96, 160, 12, 480}, - {180, 115, 352, 317, 365, 217, 752, 901, 141, 15, 341, 1, 515, 253, 700, 0, 753, 873, 2, 197, 31, 137, 165, 244, 4, 120, 160, 44, 98, 5, 202, 3}, - {5, 32, 347, 49, 13, 21, 95, 713, 23, 1, 77, 33, 60, 64, 107, 4, 126, 928, 296, 850, 0, 241, 197, 102, 652, 195, 180, 534, 165, 153, 379, 10}, - {341, 180, 365, 901, 317, 115, 15, 752, 515, 700, 217, 873, 753, 82, 0, 110, 197, 141, 951, 165, 1, 564, 13, 351, 253, 12, 10, 3, 2, 4, 308, 244}, - {17, 45, 21, 3, 106, 5, 155, 38, 227, 32, 2, 209, 62, 54, 12, 243, 14, 181, 552, 587, 46, 540, 207, 794, 37, 48, 430, 119, 255, 221, 770, 29}, - {16, 24, 35, 18, 7, 0, 50, 1, 9, 14, 75, 69, 2, 5, 12, 21, 60, 13, 67, 71, 23, 48, 10, 108, 223, 181, 189, 103, 46, 64, 92, 51}, - {127, 13, 98, 165, 308, 23, 286, 293, 258, 51, 219, 395, 197, 115, 301, 401, 31, 391, 22, 105, 457, 170, 239, 276, 55, 338, 629, 116, 180, 479, 509, 569}, - {539, 213, 748, 840, 957, 669, 30, 466, 88, 217, 144, 251, 863, 190, 137, 93, - 230, 228, 679, 352, 317, 203, 617, 321, 258, 530, 160, 219, 96, 831, 816, 689}, - {5, 48, 1, 21, 2, 14, 0, 36, 12, 38, 32, 54, 430, 181, 50, 270, 72, 99, 281, 45, 17, 10, 46, 22, 37, 218, 67, 3, 290, 76, 23, 51}, - {13, 23, 0, 4, 33, 51, 2, 115, 141, 1, 77, 217, 180, 10, 9, 317, 3, 102, 11, 5, 15, 197, 7, 202, 22, 165, 40, 64, 515, 6, 341, 31}, - {13, 15, 117, 515, 23, 12, 37, 134, 165, 700, 38, 54, 457, 753, 51, 64, 153, 197, 14, 10, 33, 82, 961, 0, 99, 89, 115, 719, 141, 3, 4, 1}, - {5, 21, 2, 3, 1, 32, 14, 12, 48, 17, 0, 10, 51, 23, 38, 22, 4, 72, 13, 54, 36, 45, 137, 76, 99, 114, 86, 37, 11, 64, 540, 430}, - {202, 128, 77, 318, 291, 33, 269, 102, 275, 141, 494, 342, 40, 678, 0, 177, 20, 210, 402, 7, 4, 5, 137, 6, 13, 450, 403, 32, 49, 120, 23, 22}, - {1, 2, 24, 14, 67, 46, 69, 50, 38, 103, 16, 18, 75, 35, 83, 29, 52, 96, 5, 108, 0, 7, 54, 71, 149, 394, 236, 309, 70, 133, 220, 58}, - {15, 515, 1, 700, 0, 2, 753, 13, 23, 5, 180, 3, 51, 4, 165, 457, 12, 197, 115, 6, 7, 21, 9, 141, 8, 901, 33, 82, 120, 77, 10, 110}, - {0, 28, 65, 14, 67, 2, 124, 24, 1, 9, 7, 69, 55, 154, 36, 16, 46, 114, 175, 35, 83, 22, 429, 18, 109, 149, 68, 189, 108, 336, 251, 133}, - {56, 162, 403, 3, 129, 775, 99, 161, 17, 40, 527, 33, 880, 4, 14, 128, 475, 12, 548, 23, 102, 202, 361, 117, 34, 184, 383, 200, 183, 196, 64, 53}, - {151, 2, 29, 58, 112, 45, 186, 113, 5, 70, 52, 1, 311, 6, 315, 66, 61, 7, 74, 27, 631, 17, 80, 87, 287, 243, 209, 227, 14, 491, 19, 869}, - {6, 1, 74, 2, 75, 29, 25, 66, 26, 70, 52, 138, 67, 324, 357, 42, 19, 220, 14, 85, 87, 108, 38, 451, 309, 103, 24, 69, 380, 135, 114, 65}, - {15, 515, 700, 13, 23, 0, 1, 120, 753, 51, 180, 2, 260, 202, 5, 141, 77, 102, 9, 450, 115, 21, 197, 165, 7, 137, 110, 33, 12, 269, 901, 4}, - {5, 45, 17, 2, 14, 46, 48, 38, 181, 50, 155, 3, 186, 54, 61, 29, 21, 227, 281, 80, 540, 106, 12, 400, 52, 1, 58, 32, 328, 171, 209, 487}, - {16, 18, 265, 121, 158, 35, 60, 9, 39, 7, 329, 105, 252, 68, 24, 1, 132, 167, 159, 22, 0, 49, 286, 101, 21, 146, 23, 327, 120, 709, 5, 14}, - {108, 467, 283, 56, 389, 650, 123, 412, 33, 177, 899, 475, 216, 453, 269, 349, 619, 65, 51, 730, 403, 670, 23, 196, 523, 128, 84, 13, 401, 789, 503, 543}, - {514, 3, 11, 377, 328, 4, 361, 507, 57, 403, 14, 880, 130, 485, 176, 215, 236, 38, 152, 102, 211, 56, 62, 757, 54, 585, 300, 556, 34, 555, 40, 229}, - {3, 555, 62, 266, 130, 99, 507, 139, 514, 12, 152, 229, 215, 305, 57, 40, 440, 33, 403, 471, 38, 56, 475, 14, 361, 313, 775, 328, 196, 548, 123, 23}, - {120, 202, 318, 15, 77, 13, 1, 450, 33, 269, 515, 260, 5, 128, 494, 51, 23, 700, 102, 141, 40, 753, 326, 403, 817, 137, 523, 21, 177, 922, 342, 7}, - {15, 1, 515, 23, 0, 13, 700, 2, 51, 753, 180, 5, 165, 21, 197, 12, 3, 120, 115, 4, 141, 6, 9, 7, 457, 33, 386, 202, 82, 8, 31, 341}, - {15, 180, 515, 82, 351, 700, 10, 317, 753, 115, 217, 365, 141, 898, 33, 901, 13, 23, 110, 854, 752, 77, 1, 197, 4, 341, 143, 36, 64, 352, 102, 9}, - {104, 289, 66, 707, 214, 90, 712, 64, 97, 173, 20, 0, 414, 194, 874, 43, 32, 7, 568, 560, 65, 38, 426, 312, 715, 192, 376, 74, 835, 5, 324, 147}, - {84, 56, 0, 554, 63, 65, 453, 249, 123, 643, 18, 26, 847, 475, 511, 403, 416, 561, 524, 289, 370, 73, 9, 19, 45, 42, 719, 194, 27, 467, 33, 730}, - {21, 346, 13, 350, 308, 826, 197, 101, 352, 68, 570, 0, 165, 23, 9, 841, 115, 100, 509, 694, 221, 230, 35, 217, 569, 88, 124, 749, 1, 777, 212, 154}, - {16, 92, 7, 24, 60, 18, 35, 140, 126, 14, 50, 71, 46, 330, 2, 75, 246, 5, 121, 267, 571, 1, 230, 309, 220, 0, 9, 64, 146, 236, 54, 108}, - {82, 15, 515, 898, 365, 700, 180, 33, 341, 753, 77, 901, 10, 115, 55, 351, 21, 5, 1, 4, 13, 102, 36, 217, 2, 165, 752, 120, 197, 117, 11, 317}, - {16, 24, 35, 18, 69, 71, 140, 1, 103, 7, 189, 68, 0, 50, 9, 108, 2, 133, 60, 267, 230, 46, 149, 67, 167, 118, 92, 14, 75, 21, 191, 38}, - {60, 71, 16, 18, 7, 20, 43, 118, 35, 68, 375, 28, 608, 0, 175, 566, 154, 92, 14, 149, 628, 33, 22, 13, 2, 10, 279, 23, 107, 356, 55, 117}, - {187, 258, 871, 295, 201, 434, 219, 224, 489, 384, 268, 110, 261, 839, 44, 699, - 93, 116, 36, 131, 141, 228, 144, 160, 940, 567, 244, 406, 137, 574, 98, 253}, - {66, 7, 97, 172, 192, 712, 232, 324, 204, 74, 43, 448, 387, 426, 568, 20, 526, 107, 104, 135, 356, 729, 173, 0, 22, 5, 32, 95, 2, 64, 500, 560}, - {15, 515, 700, 753, 1, 4, 0, 341, 13, 3, 134, 2, 5, 33, 11, 77, 12, 10, 23, 197, 365, 901, 7, 40, 217, 32, 21, 6, 51, 180, 961, 37}, - {0, 28, 24, 9, 35, 65, 16, 124, 68, 55, 109, 154, 7, 39, 22, 149, 158, 14, 175, 1, 49, 252, 18, 71, 2, 168, 289, 419, 108, 420, 67, 101}, - {7, 16, 14, 92, 2, 46, 140, 24, 220, 35, 38, 60, 75, 1, 50, 18, 87, 54, 5, 126, 29, 52, 278, 262, 314, 107, 71, 21, 172, 135, 330, 394}, - {7, 92, 16, 14, 172, 126, 2, 60, 140, 35, 135, 314, 278, 46, 24, 38, 232, 107, 330, 66, 5, 18, 150, 246, 230, 97, 52, 1, 121, 563, 279, 21}, - {6, 26, 235, 53, 297, 436, 27, 19, 25, 73, 113, 445, 90, 214, 65, 42, 64, 289, 250, 611, 624, 32, 45, 648, 614, 17, 85, 491, 34, 122, 200, 416}, - {352, 141, 1, 217, 854, 752, 351, 180, 244, 36, 110, 661, 82, 258, 816, 160, 295, 219, 567, 224, 230, 269, 922, 144, 260, 268, 93, 201, 137, 116, 489, 202}, - {16, 60, 35, 18, 126, 107, 68, 191, 92, 121, 7, 14, 598, 20, 493, 279, 167, 446, 118, 0, 28, 43, 463, 55, 24, 212, 375, 566, 9, 150, 575, 21}, - {15, 1, 515, 2, 4, 13, 0, 700, 3, 5, 23, 753, 341, 77, 51, 115, 33, 11, 180, 10, 197, 141, 6, 165, 7, 901, 102, 40, 9, 202, 217, 12}, - {23, 51, 13, 202, 21, 5, 1, 120, 15, 137, 128, 125, 32, 2, 12, 141, 33, 165, 64, 515, 403, 318, 700, 48, 180, 7, 6, 450, 115, 523, 475, 260}, - {131, 716, 224, 371, 219, 187, 737, 616, 385, 254, 9, 98, 105, 924, 31, 258, 836, 39, 127, 578, 49, 916, 44, 761, 272, 137, 944, 159, 0, 242, 442, 22}, - {15, 515, 700, 1, 753, 2, 5, 0, 4, 13, 3, 180, 11, 141, 197, 10, 341, 217, 33, 134, 165, 6, 77, 7, 317, 12, 352, 64, 365, 32, 102, 40}, - {66, 74, 7, 173, 174, 29, 192, 2, 222, 20, 226, 43, 353, 52, 712, 6, 0, 138, 500, 204, 97, 145, 64, 104, 426, 673, 355, 90, 25, 5, 65, 87}, - {5, 259, 786, 534, 590, 493, 279, 49, 13, 581, 465, 21, 929, 35, 941, 132, 147, 32, 23, 612, 362, 626, 107, 121, 178, 0, 146, 61, 48, 939, 10, 18}, - {2, 14, 16, 7, 278, 69, 135, 140, 46, 24, 267, 35, 92, 38, 1, 189, 29, 52, 309, 60, 66, 75, 71, 172, 74, 357, 18, 87, 67, 6, 230, 5}, - {165, 13, 308, 197, 391, 23, 401, 15, 51, 457, 180, 509, 115, 569, 3, 629, 961, 719, 34, 758, 317, 734, 14, 29, 46, 2, 17, 901, 38, 453, 5, 217}, - {1, 22, 2, 14, 0, 28, 7, 168, 67, 49, 65, 24, 36, 95, 5, 105, 55, 35, 12, 46, 69, 16, 114, 159, 194, 50, 10, 9, 158, 83, 164, 109}, - {34, 453, 3, 196, 130, 14, 322, 11, 47, 51, 377, 236, 361, 4, 730, 153, 514, 711, 57, 440, 62, 17, 161, 108, 176, 59, 485, 56, 162, 412, 202, 117}, - {18, 16, 21, 23, 48, 13, 24, 35, 121, 5, 156, 60, 51, 1, 7, 132, 141, 221, 163, 115, 0, 271, 447, 340, 363, 202, 125, 71, 2, 781, 22, 698}, - {165, 13, 457, 23, 197, 961, 629, 569, 341, 41, 12, 38, 401, 901, 54, 51, 115, 17, 15, 509, 421, 37, 62, 45, 719, 57, 32, 328, 117, 758, 157, 99}, - {2, 1, 77, 141, 33, 64, 3, 102, 0, 23, 13, 5, 128, 10, 6, 15, 180, 202, 269, 40, 51, 515, 7, 165, 137, 117, 318, 4, 700, 153, 197, 352}, - {68, 212, 0, 124, 101, 9, 154, 16, 562, 191, 21, 149, 65, 24, 35, 1, 118, 167, 818, 350, 520, 100, 722, 841, 264, 71, 13, 302, 478, 23, 375, 346}, - {98, 23, 48, 598, 13, 293, 541, 21, 125, 121, 51, 807, 0, 31, 35, 259, 126, 7, 386, 1, 223, 783, 10, 107, 199, 20, 221, 144, 342, 963, 49, 64}, - {21, 13, 5, 586, 1, 23, 167, 48, 33, 781, 647, 49, 165, 18, 51, 271, 77, 32, 761, 118, 0, 82, 391, 22, 146, 141, 459, 31, 197, 156, 115, 4}, - {2, 1, 5, 61, 29, 7, 58, 45, 14, 6, 425, 32, 70, 52, 290, 738, 207, 21, 72, 112, 66, 76, 655, 17, 186, 46, 64, 263, 38, 0, 128, 87}, - {39, 265, 9, 100, 1, 333, 363, 101, 18, 411, 447, 254, 166, 310, 31, 98, 264, 30, 639, 404, 156, 286, 16, 93, 593, 203, 272, 682, 0, 905, 44, 821}, - {6, 2, 1, 19, 29, 51, 26, 108, 25, 74, 5, 23, 14, 114, 13, 386, 133, 103, 42, 66, 453, 70, 309, 138, 719, 324, 65, 38, 64, 96, 52, 75}, - {20, 43, 356, 107, 49, 858, 595, 7, 414, 359, 0, 5, 392, 319, 97, 612, 422, 819, 14, 376, 173, 246, 22, 470, 147, 427, 230, 92, 197, 33, 683, 95}, - {0, 9, 68, 35, 65, 67, 114, 101, 28, 1, 124, 175, 336, 69, 154, 103, 83, 24, 189, 133, 39, 16, 50, 7, 2, 149, 55, 251, 18, 345, 230, 36}, - {23, 13, 51, 15, 0, 1, 515, 115, 165, 2, 5, 12, 700, 202, 4, 21, 141, 457, 753, 197, 10, 3, 180, 120, 32, 9, 318, 11, 453, 64, 6, 269}, - {121, 195, 60, 16, 126, 107, 98, 271, 146, 407, 132, 35, 1, 167, 199, 223, 493, 191, 279, 20, 18, 5, 43, 7, 21, 92, 48, 393, 0, 362, 212, 467}, - {31, 44, 299, 116, 393, 144, 492, 456, 268, 22, 105, 0, 367, 918, 384, 434, 127, 489, 98, 9, 963, 125, 242, 948, 1, 28, 206, 49, 36, 51, 93, 293}, - {23, 13, 457, 51, 165, 401, 719, 758, 197, 453, 961, 629, 308, 14, 15, 12, 730, 3, 386, 569, 391, 29, 739, 515, 34, 828, 832, 901, 115, 514, 670, 341}, - {105, 36, 131, 22, 180, 115, 341, 127, 169, 1, 9, 31, 64, 98, 44, 365, 317, 141, 272, 143, 160, 55, 219, 86, 197, 776, 239, 187, 0, 535, 13, 752}, - {1, 6, 2, 14, 66, 25, 29, 5, 108, 67, 65, 114, 19, 38, 26, 52, 74, 7, 24, 18, 69, 86, 36, 388, 64, 51, 17, 83, 23, 46, 42, 75}, - {51, 386, 23, 453, 719, 13, 730, 6, 457, 670, 758, 19, 401, 165, 2, 475, 47, 26, 899, 14, 108, 17, 1, 5, 197, 29, 894, 754, 236, 74, 27, 285}, - {252, 18, 9, 101, 121, 16, 132, 0, 419, 167, 364, 60, 604, 35, 265, 363, 146, 271, 39, 158, 68, 109, 28, 329, 848, 24, 647, 907, 682, 159, 212, 55}, - {283, 503, 128, 432, 26, 193, 63, 269, 789, 529, 102, 122, 389, 275, 678, 6, 25, 318, 445, 4, 342, 27, 573, 605, 177, 862, 643, 291, 216, 57, 235, 59}, - {2, 1, 29, 75, 69, 52, 14, 6, 46, 74, 87, 7, 220, 226, 278, 38, 135, 66, 267, 70, 16, 262, 25, 24, 380, 324, 357, 140, 67, 394, 97, 222}, - {97, 298, 69, 7, 66, 140, 189, 24, 16, 267, 172, 423, 60, 150, 14, 314, 92, 71, 81, 501, 43, 35, 74, 6, 517, 232, 149, 607, 83, 330, 18, 2}, - {475, 421, 403, 899, 51, 805, 523, 958, 453, 817, 23, 615, 401, 801, 120, 326, 202, 670, 494, 730, 450, 386, 115, 629, 260, 576, 77, 365, 569, 0, 165, 13}, - {7, 20, 14, 128, 77, 97, 112, 202, 2, 177, 16, 415, 269, 318, 275, 66, 107, 43, 141, 414, 135, 38, 307, 10, 58, 0, 6, 291, 32, 5, 4, 40}, - {24, 14, 7, 0, 2, 1, 22, 28, 16, 65, 168, 124, 35, 67, 108, 109, 18, 49, 10, 149, 69, 158, 5, 95, 289, 12, 55, 6, 36, 71, 46, 21}, - {26, 80, 27, 73, 122, 25, 19, 17, 6, 42, 684, 209, 445, 573, 667, 106, 45, 690, 4, 611, 255, 680, 297, 495, 65, 59, 128, 119, 483, 113, 64, 53}, - {107, 259, 362, 376, 465, 20, 470, 147, 595, 534, 612, 683, 660, 43, 5, 49, 581, 0, 858, 35, 427, 246, 97, 786, 178, 356, 14, 21, 142, 878, 7, 279}, - {131, 30, 228, 190, 856, 406, 224, 88, 219, 530, 863, 613, 778, 274, 944, 816, 187, 39, 100, 160, 258, 31, 44, 93, 1, 321, 539, 36, 871, 137, 435, 531}, - {113, 6, 311, 25, 45, 491, 80, 611, 27, 26, 209, 667, 17, 73, 122, 42, 684, 396, 19, 85, 106, 5, 614, 4, 2, 255, 151, 29, 1, 64, 648, 61}, - {15, 515, 700, 753, 0, 1, 23, 51, 120, 2, 13, 82, 5, 260, 9, 4, 341, 77, 180, 115, 141, 10, 7, 12, 450, 8, 202, 901, 197, 351, 165, 93}, - {219, 127, 98, 258, 395, 421, 924, 293, 242, 201, 697, 105, 276, 51, 308, 23, 453, 272, 401, 944, 512, 137, 13, 31, 284, 567, 386, 365, 116, 131, 964, 125}, - {15, 180, 352, 141, 515, 752, 217, 82, 1, 317, 854, 700, 351, 753, 115, 341, 110, 13, 260, 120, 21, 36, 33, 898, 23, 10, 5, 365, 4, 160, 901, 137}, - {129, 123, 17, 257, 162, 184, 205, 249, 183, 769, 5, 80, 3, 4, 229, 130, 119, 45, 90, 99, 618, 106, 57, 497, 12, 128, 2, 84, 59, 152, 27, 40}, - {33, 102, 23, 77, 64, 128, 51, 13, 0, 202, 10, 141, 40, 15, 1, 22, 117, 137, 2, 86, 4, 403, 269, 153, 515, 196, 65, 11, 700, 115, 99, 5}, - {7, 14, 2, 16, 172, 107, 46, 92, 5, 135, 35, 202, 294, 87, 38, 232, 29, 97, 20, 21, 24, 1, 60, 220, 66, 43, 12, 0, 126, 52, 54, 70}, - {403, 576, 615, 523, 475, 326, 805, 817, 494, 421, 51, 202, 120, 450, 137, 453, 23, 859, 260, 401, 402, 77, 33, 670, 0, 958, 15, 197, 386, 515, 165, 480}, - {141, 352, 217, 137, 0, 180, 202, 349, 9, 269, 23, 51, 115, 291, 77, 372, 13, 317, 120, 752, 365, 351, 93, 22, 2, 341, 64, 10, 82, 854, 28, 18}, - {1, 23, 13, 51, 202, 141, 5, 165, 21, 15, 120, 180, 64, 2, 197, 125, 33, 102, 12, 7, 137, 515, 48, 128, 269, 318, 93, 700, 0, 403, 9, 4}, - {25, 151, 6, 145, 122, 29, 174, 45, 113, 74, 4, 665, 42, 138, 2, 614, 416, 287, 19, 348, 746, 0, 66, 26, 1, 7, 64, 243, 311, 396, 81, 624}, - {30, 190, 254, 166, 100, 382, 731, 829, 88, 131, 264, 795, 9, 93, 625, 274, 438, 1, 578, 613, 716, 31, 44, 39, 530, 36, 616, 921, 265, 203, 160, 77}, - {132, 5, 21, 13, 1, 23, 32, 195, 379, 687, 156, 121, 626, 296, 48, 70, 850, 146, 51, 82, 883, 771, 35, 49, 652, 407, 60, 4, 260, 0, 845, 33}, - {9, 254, 0, 49, 272, 131, 39, 159, 688, 101, 105, 578, 518, 158, 286, 28, 327, 333, 68, 224, 252, 219, 344, 16, 22, 1, 716, 31, 30, 228, 24, 890}, - {16, 7, 35, 60, 18, 20, 14, 68, 9, 0, 28, 118, 43, 92, 126, 55, 107, 2, 101, 154, 24, 71, 5, 202, 121, 109, 22, 252, 21, 97, 1, 621}, - {15, 515, 700, 753, 13, 1, 341, 2, 0, 4, 3, 5, 11, 23, 10, 33, 117, 12, 901, 197, 6, 134, 77, 8, 165, 317, 21, 365, 217, 7, 17, 40}, - {78, 19, 444, 47, 26, 390, 27, 453, 130, 813, 108, 730, 711, 65, 412, 122, 51, 680, 113, 235, 690, 196, 630, 283, 128, 236, 14, 64, 73, 53, 200, 445}, - {2, 7, 29, 5, 61, 6, 45, 1, 66, 113, 112, 14, 52, 315, 738, 128, 32, 151, 74, 16, 20, 64, 70, 21, 592, 0, 25, 4, 425, 43, 491, 222}, - {145, 112, 74, 66, 6, 29, 26, 70, 19, 396, 25, 87, 2, 287, 135, 151, 138, 222, 5, 226, 42, 122, 7, 307, 1, 644, 45, 58, 113, 651, 635, 632}, - {92, 16, 7, 60, 126, 24, 140, 35, 14, 232, 18, 121, 246, 71, 46, 267, 172, 150, 107, 314, 132, 146, 230, 2, 278, 108, 330, 199, 236, 5, 38, 572}, - {13, 115, 197, 538, 569, 341, 98, 55, 165, 127, 365, 762, 219, 286, 844, 23, 170, 206, 734, 638, 535, 901, 169, 253, 629, 0, 873, 509, 180, 10, 332, 258}, - {58, 151, 74, 53, 287, 27, 29, 396, 6, 70, 2, 73, 5, 52, 112, 26, 651, 1, 297, 113, 17, 75, 19, 45, 334, 445, 145, 34, 315, 549, 436, 331}, - {214, 289, 90, 874, 104, 751, 64, 65, 312, 835, 204, 249, 750, 194, 74, 81, 875, 32, 519, 288, 348, 0, 174, 247, 636, 715, 138, 192, 784, 6, 524, 280}, - {9, 39, 28, 35, 30, 0, 166, 49, 1, 175, 439, 158, 64, 346, 36, 101, 67, 364, 86, 88, 274, 100, 168, 55, 23, 10, 420, 22, 190, 141, 505, 180}, - {341, 901, 15, 515, 700, 753, 1, 365, 10, 0, 569, 180, 2, 197, 115, 31, 165, 3, 5, 4, 44, 22, 317, 13, 9, 951, 23, 253, 116, 143, 762, 93}, - {120, 202, 77, 450, 260, 15, 128, 318, 102, 515, 494, 13, 817, 700, 269, 5, 403, 51, 1, 33, 23, 753, 82, 326, 141, 342, 291, 137, 21, 523, 351, 32}, - {13, 115, 241, 64, 180, 32, 125, 197, 165, 4, 118, 22, 21, 23, 16, 247, 237, 28, 225, 191, 95, 141, 167, 5, 0, 341, 288, 35, 459, 18, 177, 24}, - {16, 24, 35, 14, 1, 2, 7, 69, 18, 46, 60, 50, 267, 140, 71, 189, 108, 38, 75, 92, 0, 5, 9, 230, 67, 21, 309, 335, 54, 236, 394, 220}, - {15, 515, 700, 753, 898, 180, 901, 341, 197, 638, 10, 165, 33, 1, 115, 4, 77, 365, 317, 13, 102, 217, 117, 0, 5, 2, 253, 3, 82, 569, 21, 752}, - {193, 523, 18, 84, 56, 730, 233, 65, 4, 817, 90, 33, 643, 403, 91, 511, 453, 240, 59, 11, 214, 51, 719, 196, 153, 475, 32, 123, 64, 847, 102, 561}, - {112, 29, 151, 2, 74, 6, 66, 7, 222, 145, 287, 45, 5, 624, 52, 25, 113, 416, 58, 122, 19, 70, 186, 204, 4, 87, 644, 549, 337, 884, 32, 0}, - {13, 0, 23, 2, 1, 15, 33, 3, 77, 515, 141, 5, 4, 217, 10, 51, 64, 180, 700, 115, 6, 117, 11, 7, 753, 40, 102, 165, 197, 22, 317, 153}, - {28, 0, 1, 67, 65, 9, 2, 114, 83, 69, 103, 50, 36, 22, 55, 24, 46, 14, 124, 109, 35, 7, 16, 38, 133, 160, 389, 323, 18, 12, 154, 5}, - {121, 132, 18, 167, 271, 146, 101, 363, 621, 9, 411, 647, 16, 354, 520, 60, 212, 932, 1, 806, 55, 0, 195, 446, 68, 35, 31, 364, 777, 252, 407, 118}, - {26, 6, 85, 396, 122, 624, 25, 19, 42, 445, 64, 648, 573, 416, 174, 680, 665, 214, 45, 348, 90, 65, 194, 145, 113, 881, 138, 289, 112, 436, 297, 544}, - {16, 146, 18, 92, 24, 199, 60, 71, 121, 126, 35, 108, 156, 953, 271, 674, 132, 7, 32, 640, 360, 246, 649, 118, 21, 95, 5, 517, 14, 9, 1, 314}, - {51, 13, 23, 453, 475, 730, 719, 15, 457, 403, 64, 115, 33, 95, 4, 523, 3, 12, 21, 6, 899, 102, 5, 128, 401, 202, 11, 141, 308, 515, 22, 125}, - {151, 396, 6, 53, 27, 113, 58, 26, 73, 112, 74, 287, 45, 29, 297, 19, 145, 70, 138, 445, 315, 436, 34, 2, 17, 573, 5, 61, 549, 491, 1, 80}, - {223, 1, 888, 774, 260, 98, 269, 385, 349, 202, 96, 141, 421, 622, 730, 863, 318, 697, 87, 453, 393, 418, 922, 834, 751, 5, 163, 335, 120, 291, 352, 30}, - {16, 60, 92, 35, 126, 121, 7, 150, 246, 18, 107, 1, 598, 24, 167, 195, 14, 97, 71, 279, 98, 441, 191, 199, 517, 146, 356, 223, 298, 271, 230, 0}, - {22, 1, 105, 28, 239, 170, 0, 55, 95, 31, 36, 301, 2, 320, 98, 127, 9, 49, 44, 64, 35, 67, 10, 86, 5, 12, 109, 23, 168, 13, 21, 312}, - {2, 6, 5, 207, 292, 76, 1, 119, 45, 32, 17, 29, 61, 306, 790, 58, 240, 106, 14, 64, 214, 151, 476, 710, 7, 72, 84, 128, 4, 179, 70, 25}, - {51, 23, 221, 254, 115, 13, 438, 530, 125, 48, 21, 39, 541, 960, 386, 49, 1, 613, 15, 840, 228, 308, 627, 131, 688, 401, 5, 326, 421, 158, 165, 83}, - {1, 5, 2, 0, 12, 22, 21, 36, 10, 14, 48, 86, 23, 13, 32, 54, 3, 4, 28, 65, 51, 50, 137, 37, 208, 114, 9, 38, 17, 7, 281, 202}, - {363, 23, 447, 182, 296, 340, 1, 93, 698, 478, 379, 156, 284, 144, 18, 269, 21, 98, 141, 70, 668, 411, 664, 658, 110, 914, 67, 937, 180, 691, 335, 291}, - {17, 32, 45, 498, 41, 115, 180, 197, 106, 62, 54, 38, 546, 165, 13, 155, 468, 509, 341, 243, 241, 217, 542, 15, 57, 536, 428, 51, 117, 721, 292, 129}, - {32, 95, 64, 246, 22, 92, 180, 13, 5, 652, 125, 241, 638, 237, 7, 49, 4, 126, 21, 115, 197, 296, 888, 316, 0, 165, 774, 23, 16, 392, 1, 534}, - {15, 515, 700, 753, 33, 341, 13, 217, 4, 141, 77, 23, 180, 317, 1, 10, 102, 351, 82, 115, 40, 5, 854, 21, 137, 11, 352, 901, 365, 117, 197, 0}, - {15, 120, 1, 82, 93, 217, 515, 260, 77, 141, 13, 110, 700, 351, 352, 23, 180, 753, 21, 854, 202, 317, 64, 349, 269, 51, 165, 137, 5, 128, 291, 36}, - {13, 23, 51, 141, 77, 0, 33, 4, 115, 64, 2, 10, 102, 202, 217, 128, 1, 177, 269, 11, 7, 22, 6, 21, 32, 9, 180, 40, 15, 3, 165, 318}, - {478, 264, 1, 520, 98, 724, 9, 682, 223, 664, 21, 759, 13, 772, 604, 100, 23, 363, 411, 48, 821, 5, 0, 905, 909, 447, 31, 265, 88, 101, 166, 39}, - {20, 29, 7, 2, 77, 416, 6, 128, 33, 5, 0, 113, 104, 32, 43, 13, 491, 66, 23, 21, 102, 51, 74, 210, 202, 525, 64, 318, 10, 81, 174, 14}, - {2, 1, 5, 14, 7, 58, 61, 29, 45, 290, 46, 38, 52, 21, 32, 270, 6, 592, 425, 0, 75, 155, 16, 48, 17, 50, 72, 70, 207, 24, 263, 663}, - {80, 6, 17, 209, 106, 26, 483, 113, 19, 469, 255, 25, 378, 27, 495, 833, 45, 64, 161, 2, 61, 667, 76, 742, 32, 90, 445, 5, 814, 65, 887, 119}, - {98, 223, 393, 1, 354, 834, 195, 791, 447, 697, 284, 293, 360, 541, 781, 156, 51, 807, 18, 664, 421, 411, 163, 668, 48, 31, 591, 765, 883, 386, 948, 23}, - {679, 141, 816, 36, 93, 406, 876, 144, 228, 137, 1, 180, 669, 21, 332, 251, 5, 269, 116, 187, 96, 351, 202, 752, 317, 64, 203, 831, 574, 466, 855, 345}, - {15, 515, 700, 13, 1, 753, 2, 0, 23, 341, 3, 5, 4, 10, 51, 11, 33, 165, 6, 7, 115, 197, 12, 64, 180, 153, 217, 77, 9, 569, 901, 317}, - {13, 23, 202, 51, 5, 21, 403, 15, 120, 64, 1, 450, 128, 141, 12, 523, 33, 165, 494, 125, 2, 515, 269, 7, 48, 102, 318, 95, 260, 180, 453, 197}, - {16, 18, 24, 60, 71, 92, 146, 246, 199, 35, 140, 7, 9, 118, 121, 108, 167, 230, 126, 132, 0, 640, 156, 14, 68, 133, 267, 360, 649, 271, 64, 55}, - {269, 141, 678, 177, 202, 77, 128, 318, 33, 947, 40, 120, 291, 349, 102, 137, 64, 352, 210, 864, 461, 498, 13, 342, 196, 23, 275, 450, 954, 0, 205, 111}, - {16, 24, 92, 18, 71, 60, 35, 7, 108, 191, 167, 246, 140, 14, 126, 21, 1, 68, 150, 118, 149, 388, 399, 9, 273, 0, 121, 796, 230, 48, 212, 517}, - {2, 14, 1, 29, 46, 75, 52, 70, 69, 171, 38, 7, 58, 163, 16, 5, 24, 220, 67, 112, 223, 54, 50, 409, 155, 35, 267, 186, 151, 334, 394, 140}, - {9, 252, 100, 265, 166, 39, 88, 404, 329, 0, 1, 520, 382, 812, 101, 593, 264, 274, 604, 676, 30, 118, 68, 553, 18, 664, 363, 23, 639, 865, 21, 411}, - {16, 18, 35, 24, 0, 60, 158, 7, 22, 68, 14, 49, 109, 159, 55, 9, 28, 71, 2, 10, 5, 105, 1, 118, 329, 13, 344, 23, 92, 20, 21, 126}, - {15, 13, 515, 700, 23, 0, 753, 1, 51, 2, 4, 10, 77, 5, 3, 197, 115, 165, 961, 202, 9, 457, 180, 12, 141, 22, 33, 120, 6, 11, 318, 31}, - {160, 93, 251, 137, 317, 1, 180, 36, 120, 217, 345, 752, 617, 352, 332, 10, 96, 531, 498, 318, 365, 202, 141, 269, 816, 341, 901, 679, 143, 35, 83, 968}, - {6, 25, 42, 128, 19, 59, 122, 4, 85, 26, 611, 27, 269, 233, 45, 0, 343, 91, 318, 80, 11, 177, 283, 73, 33, 614, 2, 77, 64, 138, 445, 216}, - {95, 64, 74, 7, 32, 81, 51, 204, 0, 20, 237, 65, 56, 38, 91, 23, 207, 180, 347, 343, 29, 6, 511, 52, 49, 10, 25, 18, 554, 370, 14, 312}, - {202, 120, 326, 260, 450, 817, 494, 318, 137, 403, 128, 77, 523, 553, 859, 5, 704, 1, 15, 23, 13, 576, 7, 16, 615, 51, 682, 291, 515, 0, 21, 234}, - {20, 43, 107, 356, 362, 126, 595, 92, 359, 7, 422, 319, 493, 16, 858, 5, 392, 246, 414, 683, 60, 0, 35, 945, 441, 21, 259, 819, 49, 97, 279, 173}, - {25, 42, 6, 77, 33, 102, 0, 122, 4, 690, 29, 483, 210, 27, 21, 19, 2, 300, 18, 648, 680, 119, 117, 59, 1, 10, 342, 12, 26, 153, 91, 684}, - {31, 44, 299, 116, 125, 242, 456, 599, 22, 393, 0, 144, 492, 28, 268, 1, 9, 963, 301, 105, 367, 36, 127, 170, 384, 434, 206, 98, 918, 10, 13, 93}, - {410, 521, 686, 367, 662, 88, 335, 321, 201, 96, 98, 772, 144, 1, 934, 921, 443, 435, 284, 274, 264, 551, 120, 897, 44, 100, 33, 225, 744, 418, 909, 960}, - {142, 178, 878, 234, 132, 786, 195, 202, 77, 416, 147, 929, 146, 522, 167, 259, 687, 639, 450, 271, 626, 481, 590, 5, 198, 212, 771, 49, 0, 465, 315, 427}, - {254, 39, 131, 9, 272, 0, 578, 716, 310, 224, 30, 49, 105, 827, 518, 829, 166, 333, 616, 228, 613, 846, 101, 219, 1, 31, 890, 98, 159, 938, 252, 100}, - {230, 699, 854, 473, 450, 351, 831, 137, 855, 217, 352, 704, 800, 202, 251, 498, - 160, 144, 206, 203, 317, 201, 253, 752, 418, 141, 1, 332, 82, 180, 443, 36}, - {403, 202, 475, 453, 494, 23, 51, 77, 318, 402, 13, 33, 128, 102, 137, 141, 120, 342, 269, 0, 450, 4, 899, 576, 40, 421, 275, 117, 217, 177, 196, 64}, - {23, 44, 98, 182, 291, 144, 116, 39, 110, 141, 96, 82, 905, 70, 367, 264, 125, 93, 77, 411, 120, 1, 658, 202, 100, 415, 107, 363, 197, 30, 447, 105}, - {15, 515, 1, 13, 700, 23, 77, 120, 0, 753, 51, 180, 202, 141, 260, 5, 21, 115, 2, 137, 128, 9, 450, 197, 365, 269, 12, 326, 110, 102, 318, 7}, - {0, 32, 18, 95, 207, 577, 193, 29, 61, 104, 64, 784, 715, 102, 693, 887, 81, 91, 583, 671, 403, 5, 52, 474, 397, 180, 138, 49, 37, 344, 38, 263}, - {0, 101, 9, 68, 252, 16, 100, 39, 166, 364, 124, 24, 154, 265, 212, 88, 18, 35, 329, 419, 28, 118, 71, 30, 65, 158, 191, 55, 1, 694, 21, 676}, - {16, 24, 191, 18, 35, 71, 167, 118, 149, 68, 212, 9, 0, 1, 21, 108, 101, 92, 60, 375, 302, 7, 589, 755, 124, 674, 350, 48, 562, 246, 13, 363}, - {2, 14, 69, 24, 1, 67, 46, 16, 38, 103, 29, 267, 7, 35, 189, 135, 278, 71, 108, 18, 83, 309, 52, 6, 149, 388, 75, 236, 60, 0, 150, 66}, - {13, 1, 23, 0, 4, 2, 51, 15, 180, 33, 3, 115, 5, 515, 141, 10, 77, 700, 11, 9, 197, 341, 202, 165, 217, 102, 22, 7, 753, 317, 365, 6}, - {447, 1, 698, 411, 31, 363, 98, 5, 919, 4, 156, 125, 759, 691, 13, 64, 459, 354, 44, 21, 48, 293, 30, 914, 478, 225, 82, 120, 2, 922, 848, 839}, - {854, 82, 351, 217, 141, 180, 352, 15, 515, 752, 1, 700, 317, 898, 753, 244, 10, 21, 922, 115, 77, 36, 4, 260, 64, 110, 372, 13, 5, 365, 120, 11}, - {0, 1, 4, 13, 5, 2, 82, 33, 3, 120, 10, 23, 9, 11, 77, 260, 21, 102, 8, 31, 40, 6, 351, 51, 64, 450, 22, 117, 93, 110, 7, 457}, - {51, 13, 403, 23, 12, 475, 1, 2, 21, 5, 453, 523, 115, 202, 817, 7, 0, 99, 3, 6, 450, 120, 494, 64, 22, 95, 49, 899, 10, 37, 32, 141}, - {180, 752, 352, 141, 498, 864, 317, 217, 9, 0, 115, 237, 230, 39, 30, 197, 83, 1, 930, 64, 35, 365, 372, 13, 579, 88, 702, 36, 101, 901, 482, 21}, - {16, 24, 0, 7, 22, 18, 28, 35, 14, 158, 71, 2, 109, 60, 1, 168, 49, 154, 124, 68, 10, 55, 92, 118, 159, 9, 5, 747, 95, 105, 65, 6}, - {15, 515, 700, 753, 0, 23, 1, 13, 341, 51, 120, 77, 141, 4, 137, 33, 260, 82, 202, 9, 180, 5, 351, 2, 291, 10, 11, 901, 21, 115, 40, 128}, - {24, 68, 35, 149, 18, 16, 0, 7, 9, 14, 189, 108, 69, 65, 67, 1, 71, 2, 118, 28, 140, 101, 114, 336, 230, 124, 175, 133, 46, 55, 251, 154}, - {13, 308, 197, 115, 125, 9, 165, 237, 391, 23, 509, 569, 546, 28, 49, 629, 22, 338, 317, 254, 749, 180, 468, 159, 903, 386, 217, 352, 558, 39, 36, 734}, - {64, 90, 32, 217, 77, 4, 141, 216, 172, 312, 128, 13, 86, 33, 597, 147, 352, 95, 5, 115, 875, 22, 59, 11, 102, 14, 182, 437, 97, 177, 874, 707}, - {1, 22, 36, 0, 105, 28, 2, 67, 95, 49, 55, 5, 239, 12, 86, 9, 83, 170, 312, 64, 31, 21, 23, 10, 164, 50, 114, 159, 208, 13, 7, 320}, - {9, 18, 16, 0, 159, 105, 101, 252, 49, 310, 24, 68, 35, 39, 265, 272, 7, 1, 60, 28, 455, 890, 329, 557, 118, 286, 55, 137, 327, 167, 5, 13}, - {129, 123, 214, 249, 618, 17, 5, 257, 205, 184, 460, 76, 2, 162, 769, 245, 90, 106, 128, 45, 119, 1, 183, 4, 3, 12, 179, 64, 6, 229, 99, 209}, - {51, 453, 719, 457, 23, 13, 730, 899, 475, 386, 4, 15, 11, 12, 670, 196, 515, 523, 961, 401, 153, 3, 700, 99, 753, 117, 403, 32, 120, 165, 57, 0}, - {173, 66, 192, 204, 20, 74, 104, 636, 7, 43, 289, 426, 825, 712, 560, 214, 81, 750, 65, 97, 707, 0, 90, 414, 64, 348, 32, 500, 22, 861, 95, 6}, - {13, 23, 1, 51, 5, 21, 141, 120, 202, 15, 165, 2, 515, 180, 12, 125, 0, 64, 82, 700, 197, 269, 32, 48, 260, 128, 115, 93, 9, 137, 33, 753}, - {200, 34, 322, 78, 472, 390, 27, 714, 19, 14, 136, 161, 453, 176, 236, 444, 59, 3, 62, 128, 108, 57, 283, 862, 73, 53, 47, 17, 412, 813, 4, 56}, - {33, 347, 66, 204, 426, 498, 56, 172, 97, 95, 5, 681, 546, 22, 10, 0, 135, 180, 4, 241, 19, 174, 6, 353, 263, 21, 7, 370, 42, 197, 27, 808}, - {131, 224, 219, 187, 385, 371, 258, 442, 254, 737, 31, 98, 836, 127, 924, 944, 44, 871, 908, 716, 39, 827, 201, 574, 116, 137, 36, 1, 276, 242, 578, 616}, - {1, 15, 2, 180, 4, 141, 13, 515, 0, 5, 3, 115, 700, 901, 341, 23, 217, 352, 753, 51, 197, 77, 317, 33, 365, 752, 165, 21, 6, 7, 269, 93}, - {370, 91, 718, 74, 81, 510, 397, 66, 636, 240, 355, 84, 138, 511, 18, 278, 6, 681, 701, 289, 90, 5, 214, 582, 64, 104, 0, 643, 192, 65, 750, 32}, - {15, 515, 700, 753, 13, 120, 1, 0, 165, 2, 197, 23, 260, 180, 4, 82, 51, 386, 8, 5, 12, 10, 3, 141, 351, 341, 326, 9, 450, 7, 64, 6}, - {32, 2, 76, 5, 1, 292, 72, 45, 476, 214, 21, 241, 29, 14, 17, 48, 129, 90, 179, 460, 464, 123, 290, 148, 519, 205, 3, 263, 249, 38, 710, 89}, - {13, 165, 115, 17, 197, 569, 23, 509, 457, 45, 32, 41, 106, 180, 62, 38, 659, 734, 155, 536, 341, 629, 961, 873, 587, 54, 431, 37, 391, 99, 405, 428}, - {68, 24, 35, 16, 0, 101, 9, 124, 154, 71, 149, 65, 18, 175, 28, 118, 7, 55, 302, 108, 92, 14, 22, 346, 1, 39, 429, 252, 375, 364, 10, 67}, - {0, 9, 1, 68, 230, 65, 35, 69, 83, 23, 101, 13, 141, 67, 217, 352, 21, 39, 16, 88, 28, 124, 212, 100, 115, 154, 51, 64, 30, 36, 10, 317}, - {100, 265, 88, 909, 410, 382, 812, 593, 1, 213, 321, 30, 252, 230, 352, 264, 9, 166, 689, 39, 676, 98, 21, 466, 724, 639, 478, 217, 13, 48, 553, 101}, - {113, 61, 198, 904, 43, 0, 5, 37, 899, 325, 20, 59, 33, 523, 204, 725, 817, 389, 470, 329, 222, 40, 174, 58, 22, 453, 690, 848, 122, 104, 788, 105}, - {16, 24, 141, 18, 7, 0, 71, 140, 35, 269, 75, 352, 12, 9, 108, 217, 5, 330, 60, 64, 199, 70, 22, 13, 486, 246, 318, 133, 65, 50, 23, 498}, - {271, 167, 121, 60, 18, 191, 146, 199, 16, 1, 446, 132, 575, 212, 463, 354, 126, 35, 598, 566, 727, 98, 107, 21, 608, 955, 640, 407, 5, 24, 223, 68}, - {15, 515, 115, 217, 700, 13, 317, 753, 141, 180, 33, 23, 110, 120, 4, 341, 82, 10, 1, 260, 365, 36, 64, 854, 351, 21, 51, 352, 137, 77, 40, 0}, - {173, 7, 97, 356, 43, 107, 20, 387, 729, 104, 426, 232, 560, 595, 359, 392, 414, 707, 885, 81, 5, 0, 66, 858, 612, 49, 861, 14, 22, 32, 819, 230}, - {15, 515, 700, 753, 13, 23, 51, 82, 0, 33, 165, 120, 196, 4, 1, 2, 197, 453, 260, 351, 180, 12, 40, 8, 386, 110, 5, 326, 9, 141, 217, 457}, - {9, 100, 120, 30, 77, 795, 137, 82, 202, 39, 264, 827, 578, 127, 0, 166, 373, 318, 18, 326, 141, 260, 1, 450, 731, 31, 33, 395, 217, 291, 341, 254}, - {14, 2, 67, 1, 24, 69, 0, 28, 65, 7, 46, 18, 114, 108, 36, 83, 38, 398, 9, 16, 124, 133, 103, 154, 50, 55, 22, 267, 29, 160, 35, 547}, - {14, 7, 69, 24, 66, 16, 2, 267, 189, 67, 71, 150, 140, 97, 18, 60, 172, 35, 6, 1, 38, 149, 388, 92, 83, 135, 108, 74, 462, 380, 29, 36}, - {15, 515, 700, 753, 1, 13, 2, 0, 4, 341, 5, 3, 23, 365, 11, 117, 180, 10, 12, 33, 134, 115, 77, 197, 217, 165, 6, 7, 317, 102, 21, 9}, - {1, 22, 0, 12, 5, 2, 36, 28, 21, 10, 86, 13, 23, 49, 128, 9, 95, 51, 55, 96, 208, 141, 48, 202, 4, 137, 37, 64, 105, 3, 50, 7}, - {605, 630, 63, 123, 736, 650, 65, 108, 444, 368, 561, 389, 19, 25, 42, 619, 122, 194, 183, 27, 53, 33, 84, 26, 297, 813, 114, 73, 256, 235, 249, 216}, - {127, 39, 9, 0, 31, 371, 98, 254, 1, 385, 395, 44, 30, 836, 187, 131, 100, 116, 284, 578, 299, 166, 28, 21, 737, 16, 276, 272, 23, 49, 137, 935}, - {2, 61, 6, 29, 45, 151, 1, 655, 7, 207, 32, 5, 112, 425, 17, 76, 833, 4, 14, 64, 58, 106, 119, 25, 113, 128, 72, 52, 70, 21, 292, 790}, - {2, 5, 17, 14, 3, 29, 23, 27, 13, 401, 46, 6, 51, 58, 1, 453, 45, 53, 34, 52, 133, 19, 236, 26, 181, 114, 99, 366, 151, 108, 218, 38}, - {31, 22, 170, 1, 301, 44, 127, 98, 36, 28, 55, 105, 239, 0, 338, 116, 512, 299, 293, 125, 86, 10, 242, 395, 2, 13, 9, 64, 841, 23, 95, 685}, - {1, 21, 2, 14, 5, 32, 48, 50, 38, 270, 46, 76, 290, 72, 45, 54, 17, 0, 155, 221, 263, 207, 37, 281, 430, 3, 89, 12, 181, 408, 36, 67}, - {17, 106, 119, 378, 84, 240, 62, 80, 383, 136, 306, 3, 56, 790, 742, 5, 207, 504, 64, 440, 32, 128, 45, 2, 123, 209, 14, 4, 61, 57, 297, 667}, - {13, 15, 1, 515, 23, 2, 0, 700, 4, 115, 3, 51, 5, 10, 753, 180, 33, 341, 217, 11, 165, 317, 365, 197, 6, 77, 40, 64, 22, 9, 7, 117}, - {772, 335, 96, 744, 1, 367, 662, 686, 652, 897, 303, 264, 521, 31, 225, 410, 141, 520, 260, 116, 64, 44, 321, 98, 144, 88, 919, 966, 340, 269, 349, 284}, - {1, 0, 5, 28, 36, 2, 12, 22, 83, 67, 65, 50, 24, 14, 9, 96, 21, 218, 18, 114, 48, 281, 54, 10, 7, 160, 181, 103, 37, 23, 133, 99}, - {25, 6, 145, 42, 138, 81, 174, 348, 525, 544, 26, 74, 85, 280, 287, 648, 746, 91, 66, 0, 29, 396, 204, 64, 636, 90, 122, 194, 355, 104, 65, 233}, - {16, 24, 0, 18, 28, 158, 7, 35, 49, 22, 68, 159, 55, 1, 14, 109, 105, 2, 9, 71, 65, 154, 124, 95, 424, 344, 60, 239, 118, 577, 21, 10}, - {352, 854, 699, 230, 93, 689, 137, 144, 217, 160, 251, 36, 669, 202, 351, 120, 617, 855, 752, 203, 332, 82, 450, 180, 141, 748, 831, 30, 258, 201, 1, 816}, - {15, 13, 515, 700, 1, 2, 0, 753, 23, 5, 4, 3, 51, 33, 10, 115, 11, 317, 217, 77, 180, 341, 117, 165, 6, 134, 197, 153, 64, 9, 102, 7}, - {104, 20, 43, 173, 66, 319, 0, 77, 202, 7, 198, 5, 97, 580, 355, 74, 2, 204, 174, 52, 712, 234, 426, 155, 102, 192, 32, 4, 500, 337, 226, 904}, - {13, 23, 15, 51, 1, 515, 0, 2, 5, 700, 141, 4, 753, 165, 115, 12, 3, 21, 457, 10, 180, 269, 32, 6, 197, 202, 9, 7, 120, 11, 77, 33}, - {15, 515, 700, 753, 0, 1, 13, 2, 23, 115, 4, 317, 8, 3, 5, 51, 9, 341, 10, 217, 22, 365, 33, 457, 6, 180, 77, 901, 197, 120, 18, 7}, - {15, 515, 700, 753, 1, 0, 2, 3, 4, 13, 5, 141, 23, 16, 82, 217, 457, 10, 365, 180, 9, 317, 51, 21, 269, 898, 64, 202, 11, 12, 318, 341}, - {2, 5, 1, 14, 50, 38, 29, 17, 114, 46, 133, 3, 45, 21, 58, 171, 181, 36, 218, 12, 6, 52, 0, 48, 137, 65, 361, 23, 155, 4, 285, 51}, - {0, 68, 9, 65, 101, 124, 35, 212, 16, 149, 154, 100, 24, 1, 114, 336, 67, 589, 252, 39, 71, 189, 69, 562, 18, 13, 30, 398, 118, 88, 265, 264}, - {1, 2, 14, 22, 0, 7, 67, 65, 28, 36, 24, 46, 168, 5, 86, 69, 38, 16, 49, 12, 289, 10, 194, 50, 83, 114, 95, 6, 18, 23, 55, 158}, - {13, 23, 15, 51, 515, 0, 700, 4, 1, 753, 2, 10, 115, 961, 457, 12, 33, 11, 3, 5, 197, 9, 165, 77, 102, 403, 453, 40, 64, 22, 37, 59}, - {15, 515, 700, 753, 0, 1, 2, 13, 23, 5, 51, 901, 8, 9, 180, 3, 7, 82, 4, 120, 12, 10, 719, 341, 6, 31, 141, 457, 197, 22, 115, 93}, - {100, 252, 88, 101, 0, 265, 9, 724, 48, 1, 21, 352, 213, 676, 410, 382, 321, 230, 30, 329, 593, 909, 39, 812, 553, 217, 23, 689, 520, 264, 166, 419}, - {2, 5, 1, 58, 171, 14, 46, 50, 29, 52, 45, 38, 186, 155, 67, 54, 151, 281, 334, 61, 48, 96, 17, 181, 103, 400, 502, 227, 21, 223, 12, 69}, - {23, 120, 13, 1, 202, 141, 51, 21, 165, 128, 260, 15, 5, 269, 137, 64, 33, 180, 82, 318, 93, 197, 77, 326, 515, 125, 110, 700, 450, 2, 32, 48}, - {341, 197, 10, 901, 13, 15, 8, 638, 569, 515, 479, 23, 180, 873, 700, 165, 143, 642, 0, 961, 753, 951, 1, 115, 509, 499, 116, 12, 498, 242, 82, 206}, - {15, 1, 23, 13, 515, 21, 120, 51, 2, 141, 202, 700, 5, 180, 165, 0, 753, 197, 12, 7, 33, 260, 352, 137, 269, 4, 82, 128, 48, 9, 110, 6}, - {2, 29, 50, 58, 1, 6, 5, 52, 14, 262, 17, 46, 27, 53, 151, 34, 171, 74, 324, 26, 38, 309, 45, 113, 19, 96, 287, 396, 223, 67, 73, 583}, - {13, 23, 141, 51, 4, 202, 0, 115, 77, 2, 33, 217, 5, 317, 180, 64, 10, 269, 3, 9, 15, 21, 1, 128, 102, 137, 318, 11, 352, 515, 22, 31}, - {1, 67, 0, 24, 50, 5, 14, 18, 16, 69, 2, 9, 103, 35, 83, 12, 96, 28, 54, 7, 58, 223, 21, 46, 281, 48, 65, 181, 22, 38, 36, 108}, - {13, 23, 141, 51, 77, 64, 202, 115, 33, 102, 128, 4, 0, 269, 10, 21, 217, 32, 180, 318, 9, 137, 2, 11, 22, 291, 7, 177, 16, 31, 165, 197}, - {317, 115, 180, 365, 873, 498, 217, 341, 13, 752, 482, 197, 569, 352, 1, 901, 36, 23, 457, 468, 165, 346, 546, 143, 509, 134, 579, 876, 868, 2, 332, 21}, - {184, 257, 205, 229, 152, 17, 57, 497, 266, 432, 452, 524, 5, 619, 381, 32, 4, 90, 2, 12, 313, 128, 45, 59, 245, 106, 3, 471, 129, 769, 339, 214}, - {13, 23, 1, 0, 15, 2, 4, 515, 51, 3, 10, 33, 5, 700, 115, 180, 753, 77, 11, 365, 341, 217, 9, 6, 197, 7, 102, 165, 317, 40, 22, 64}, - {626, 70, 771, 687, 379, 846, 767, 761, 518, 878, 82, 481, 31, 786, 49, 591, 178, 163, 407, 44, 87, 13, 845, 125, 590, 371, 195, 120, 98, 557, 937, 351}, - {264, 1, 410, 909, 772, 897, 686, 521, 335, 478, 98, 96, 691, 639, 100, 44, 284, 382, 31, 321, 744, 88, 914, 724, 662, 765, 223, 9, 682, 363, 0, 367}, - {13, 23, 1, 2, 0, 15, 51, 515, 5, 10, 4, 33, 115, 77, 180, 700, 3, 141, 217, 40, 6, 753, 317, 197, 64, 165, 7, 11, 102, 9, 341, 22}, - {141, 77, 13, 64, 269, 23, 115, 21, 318, 217, 5, 202, 102, 33, 137, 2, 15, 291, 177, 51, 48, 180, 32, 4, 515, 352, 128, 7, 0, 10, 96, 11}, - {13, 15, 23, 515, 51, 0, 700, 753, 1, 2, 4, 10, 33, 11, 961, 453, 115, 40, 457, 14, 12, 3, 9, 5, 165, 401, 197, 77, 22, 21, 64, 102}, - {1, 22, 0, 36, 2, 31, 5, 12, 13, 105, 28, 9, 49, 86, 141, 21, 23, 95, 128, 55, 44, 115, 170, 10, 164, 98, 180, 4, 137, 239, 83, 51}, - {100, 101, 88, 0, 252, 9, 265, 30, 21, 39, 759, 724, 213, 329, 321, 13, 419, 68, 562, 382, 676, 352, 694, 35, 553, 410, 1, 166, 909, 593, 230, 23}, - {539, 88, 30, 190, 321, 530, 840, 144, 669, 435, 957, 748, 778, 100, 96, 418, 203, 213, 1, 131, 410, 228, 466, 274, 36, 382, 219, 863, 613, 83, 822, 352}, - {7, 97, 92, 173, 298, 107, 43, 314, 232, 140, 16, 356, 20, 387, 729, 362, 126, 359, 246, 14, 230, 501, 426, 441, 0, 5, 560, 66, 104, 779, 35, 60}, - {2, 14, 7, 1, 58, 5, 46, 16, 38, 70, 75, 45, 24, 155, 29, 0, 21, 52, 61, 163, 220, 50, 69, 270, 35, 48, 32, 171, 18, 6, 64, 54}, - {447, 411, 363, 664, 647, 98, 621, 1, 354, 271, 223, 478, 18, 777, 781, 936, 360, 759, 167, 132, 121, 48, 21, 156, 9, 195, 118, 293, 23, 691, 13, 264}, - {2, 1, 14, 65, 36, 67, 0, 7, 46, 22, 69, 5, 38, 24, 28, 6, 83, 29, 86, 114, 168, 50, 124, 208, 12, 18, 108, 10, 194, 484, 103, 16}, - {421, 386, 51, 791, 730, 958, 165, 801, 23, 453, 697, 403, 615, 13, 221, 523, 24, 899, 401, 326, 551, 670, 576, 102, 18, 33, 125, 77, 566, 115, 203, 197}, - {104, 319, 422, 945, 0, 81, 20, 43, 715, 32, 784, 693, 879, 7, 397, 74, 306, 207, 52, 681, 671, 2, 61, 173, 6, 636, 904, 95, 887, 5, 18, 192}, - {2, 29, 1, 46, 14, 52, 70, 262, 6, 26, 50, 67, 75, 96, 309, 38, 103, 112, 58, 19, 5, 163, 145, 83, 74, 220, 223, 357, 24, 69, 331, 25}, - {786, 929, 590, 771, 687, 626, 941, 178, 465, 259, 70, 5, 13, 21, 35, 534, 107, 518, 132, 49, 878, 48, 146, 121, 379, 279, 31, 767, 147, 195, 108, 125}, - {5, 2, 186, 45, 17, 29, 48, 50, 14, 61, 46, 155, 400, 1, 227, 171, 52, 58, 38, 54, 430, 209, 80, 281, 3, 106, 536, 311, 181, 243, 21, 502}, - {0, 32, 64, 95, 817, 494, 342, 403, 207, 202, 194, 389, 453, 365, 312, 180, 316, 5, 690, 237, 848, 577, 450, 61, 102, 523, 475, 289, 49, 241, 65, 482}, - {23, 13, 51, 15, 202, 515, 1, 0, 2, 12, 115, 4, 700, 5, 165, 753, 77, 457, 21, 141, 128, 10, 3, 64, 403, 32, 197, 318, 9, 11, 33, 117}, - {119, 2, 6, 76, 5, 17, 45, 292, 306, 240, 32, 1, 19, 84, 64, 61, 4, 209, 710, 80, 26, 0, 106, 27, 214, 25, 128, 129, 29, 179, 3, 113}, - {15, 515, 700, 1, 753, 0, 13, 23, 180, 120, 51, 2, 5, 33, 165, 197, 9, 450, 7, 260, 115, 523, 4, 12, 202, 141, 82, 77, 21, 102, 8, 6}, - {6, 138, 74, 280, 222, 85, 66, 226, 25, 42, 87, 204, 64, 337, 29, 135, 95, 174, 235, 26, 145, 65, 19, 32, 792, 294, 112, 52, 256, 2, 5, 22}, - {39, 9, 0, 101, 333, 158, 49, 252, 310, 254, 272, 68, 16, 18, 159, 286, 344, 455, 30, 109, 627, 327, 24, 105, 419, 100, 364, 22, 35, 1, 329, 709}, - {21, 5, 32, 14, 2, 1, 38, 72, 76, 54, 17, 3, 48, 221, 270, 0, 45, 46, 12, 181, 37, 89, 36, 50, 540, 290, 430, 10, 4, 741, 99, 23}, - {120, 137, 202, 269, 141, 260, 318, 450, 922, 494, 77, 291, 82, 15, 5, 351, 128, 1, 515, 326, 64, 854, 700, 352, 342, 21, 753, 678, 349, 32, 523, 90}, - {16, 24, 68, 35, 71, 18, 149, 118, 191, 167, 9, 0, 212, 124, 65, 246, 7, 67, 140, 189, 399, 101, 133, 60, 1, 108, 267, 114, 69, 92, 695, 154}, - {28, 0, 9, 67, 1, 22, 109, 36, 55, 65, 194, 114, 39, 83, 49, 69, 2, 35, 103, 50, 158, 208, 86, 420, 168, 289, 505, 24, 7, 185, 5, 323}, - {147, 325, 198, 427, 142, 178, 202, 798, 5, 376, 20, 318, 259, 43, 120, 450, 77, 234, 534, 904, 470, 465, 878, 725, 329, 14, 315, 0, 260, 858, 70, 61}, - {28, 0, 65, 9, 109, 1, 55, 67, 35, 22, 24, 39, 289, 7, 175, 14, 114, 2, 158, 124, 420, 194, 68, 16, 336, 36, 49, 69, 168, 570, 154, 505}, - {141, 180, 13, 115, 1, 23, 4, 269, 2, 202, 0, 317, 217, 51, 15, 5, 21, 352, 77, 318, 3, 752, 197, 10, 165, 365, 137, 341, 9, 515, 33, 64}, - {15, 515, 700, 0, 753, 1, 2, 13, 23, 9, 51, 5, 4, 901, 33, 7, 8, 3, 12, 93, 180, 120, 197, 6, 82, 341, 10, 141, 22, 260, 457, 115}, - {6, 74, 66, 1, 25, 75, 324, 380, 278, 26, 138, 85, 135, 500, 87, 42, 220, 841, 97, 350, 29, 19, 70, 226, 38, 21, 52, 606, 235, 889, 2, 14}, - {13, 23, 51, 12, 4, 15, 453, 0, 457, 1, 403, 165, 115, 3, 11, 2, 64, 5, 401, 10, 515, 37, 202, 33, 40, 32, 99, 475, 197, 700, 308, 17}, - {788, 180, 5, 83, 693, 319, 314, 4, 32, 21, 17, 11, 817, 3, 510, 498, 33, 12, 24, 104, 814, 120, 64, 117, 306, 804, 523, 450, 288, 160, 102, 43}, - {15, 1, 515, 13, 2, 700, 23, 0, 4, 753, 3, 341, 5, 51, 33, 11, 10, 6, 77, 7, 115, 102, 180, 165, 141, 9, 197, 217, 901, 40, 12, 64}, - {101, 18, 9, 167, 520, 16, 0, 118, 60, 212, 604, 364, 694, 24, 55, 252, 68, 917, 264, 35, 1, 121, 146, 363, 39, 100, 806, 5, 21, 166, 191, 28}, - {13, 23, 0, 33, 51, 141, 77, 4, 64, 2, 115, 217, 9, 102, 7, 202, 21, 10, 180, 3, 15, 128, 5, 269, 6, 32, 11, 16, 165, 352, 22, 317}, - {66, 135, 97, 74, 172, 6, 278, 7, 204, 324, 138, 174, 29, 85, 2, 87, 25, 140, 92, 192, 52, 38, 802, 69, 448, 500, 808, 620, 22, 1, 280, 232}, - {2, 24, 69, 6, 97, 7, 1, 0, 14, 298, 423, 66, 67, 29, 150, 25, 189, 267, 124, 74, 607, 18, 36, 81, 172, 33, 83, 38, 52, 273, 71, 809}, - {0, 9, 158, 39, 68, 49, 109, 16, 24, 333, 35, 344, 101, 22, 159, 254, 272, 30, 124, 65, 28, 18, 793, 154, 310, 252, 327, 105, 627, 419, 286, 55}, - {15, 515, 700, 10, 753, 33, 77, 180, 4, 341, 1, 197, 13, 115, 365, 23, 901, 317, 5, 102, 11, 217, 165, 117, 141, 40, 2, 3, 253, 21, 134, 55}, - {100, 166, 382, 478, 265, 264, 88, 39, 98, 1, 404, 274, 9, 593, 724, 921, 639, 438, 363, 682, 411, 31, 30, 812, 96, 447, 821, 905, 252, 0, 223, 435}, - {19, 283, 436, 53, 297, 26, 813, 432, 27, 128, 42, 25, 390, 503, 122, 736, 73, 123, 605, 63, 389, 529, 630, 250, 690, 65, 381, 444, 6, 269, 108, 216}, - {33, 202, 13, 128, 494, 0, 51, 141, 269, 1, 4, 2, 102, 180, 15, 137, 65, 95, 6, 450, 77, 40, 117, 59, 457, 36, 196, 817, 134, 86, 49, 515}, - {18, 16, 60, 68, 101, 167, 191, 118, 35, 121, 9, 212, 55, 0, 126, 1, 24, 647, 199, 146, 520, 107, 628, 621, 363, 71, 21, 28, 346, 92, 806, 727}, - {352, 230, 217, 531, 160, 93, 36, 669, 748, 854, 689, 258, 137, 871, 728, 699, 752, 251, 574, 202, 373, 351, 228, 120, 717, 260, 144, 219, 268, 82, 816, 1}, - {15, 515, 700, 753, 13, 23, 0, 51, 8, 1, 4, 82, 165, 77, 110, 33, 10, 180, 5, 202, 11, 22, 120, 12, 9, 197, 115, 93, 403, 141, 40, 351}, - {0, 9, 101, 217, 35, 88, 352, 100, 39, 175, 30, 68, 562, 752, 13, 317, 252, 115, 180, 197, 64, 1, 83, 141, 65, 213, 165, 230, 194, 36, 28, 265}, - {32, 64, 5, 470, 288, 90, 21, 147, 0, 95, 356, 22, 20, 519, 835, 312, 819, 18, 247, 182, 11, 97, 13, 4, 387, 49, 43, 298, 316, 48, 107, 7}, - {16, 14, 24, 1, 7, 2, 35, 0, 5, 50, 18, 69, 46, 12, 58, 75, 9, 67, 70, 163, 21, 54, 38, 48, 223, 502, 281, 37, 140, 60, 28, 10}, - {18, 265, 9, 252, 39, 195, 354, 411, 1, 16, 132, 101, 121, 682, 167, 203, 5, 363, 146, 593, 35, 333, 21, 271, 60, 13, 100, 0, 156, 327, 7, 520}, - {4, 13, 1, 115, 141, 23, 2, 180, 5, 0, 51, 3, 217, 202, 77, 15, 33, 269, 341, 318, 317, 21, 165, 515, 11, 10, 197, 365, 9, 137, 64, 352}, - {7, 24, 16, 14, 71, 35, 18, 92, 140, 189, 108, 149, 68, 60, 69, 150, 2, 230, 97, 66, 0, 458, 67, 1, 65, 251, 38, 314, 388, 267, 36, 46}, - {1, 22, 31, 36, 0, 2, 44, 5, 141, 105, 180, 170, 12, 64, 13, 98, 86, 55, 23, 21, 28, 164, 115, 127, 10, 125, 128, 4, 9, 239, 352, 197}, - {66, 7, 97, 2, 192, 20, 52, 43, 135, 74, 560, 107, 104, 0, 750, 147, 414, 29, 580, 173, 324, 376, 226, 194, 77, 174, 204, 38, 356, 64, 16, 470}, - {0, 101, 9, 68, 35, 124, 24, 65, 39, 16, 252, 100, 154, 166, 28, 364, 149, 694, 30, 88, 55, 346, 1, 419, 71, 439, 265, 289, 22, 21, 175, 158}, - {39, 9, 100, 30, 127, 0, 737, 856, 31, 836, 827, 254, 98, 931, 166, 88, 93, 1, 44, 190, 131, 228, 120, 395, 625, 385, 863, 264, 219, 373, 110, 28}, - {5, 17, 2, 3, 21, 45, 14, 155, 48, 32, 38, 1, 328, 181, 186, 46, 23, 51, 12, 61, 227, 29, 106, 54, 99, 133, 62, 832, 13, 37, 514, 543}, - {131, 613, 30, 224, 228, 716, 274, 100, 827, 406, 219, 856, 39, 190, 31, 88, 1, 166, 9, 44, 829, 863, 931, 93, 0, 187, 625, 924, 127, 98, 137, 254}, - {352, 217, 64, 141, 752, 269, 180, 864, 437, 372, 954, 115, 498, 177, 77, 349, 317, 318, 579, 291, 947, 197, 247, 0, 23, 717, 237, 304, 128, 457, 776, 678}, - {141, 217, 180, 317, 352, 115, 15, 341, 1, 23, 13, 365, 515, 752, 2, 64, 0, 5, 498, 700, 372, 165, 51, 237, 753, 77, 244, 197, 137, 4, 21, 253}, - {5, 2, 17, 14, 1, 45, 3, 38, 21, 29, 181, 58, 46, 48, 50, 133, 114, 171, 61, 155, 32, 6, 186, 281, 361, 12, 36, 54, 4, 13, 52, 514}, - {6, 2, 119, 25, 790, 4, 45, 483, 655, 113, 1, 29, 76, 26, 32, 19, 887, 17, 128, 0, 292, 833, 59, 61, 106, 64, 77, 814, 14, 151, 84, 42}, - {13, 23, 2, 0, 51, 4, 1, 115, 141, 3, 5, 180, 33, 217, 77, 9, 202, 11, 7, 15, 10, 6, 317, 64, 21, 197, 515, 165, 102, 128, 22, 269}, - {13, 23, 51, 202, 21, 5, 1, 15, 141, 165, 120, 2, 115, 12, 32, 0, 515, 128, 318, 64, 125, 700, 4, 403, 197, 453, 180, 457, 3, 7, 10, 6}, - {9, 39, 31, 30, 0, 127, 1, 44, 100, 131, 98, 187, 385, 276, 88, 442, 219, 908, 254, 116, 49, 166, 935, 28, 201, 36, 141, 827, 137, 299, 284, 21}, - {22, 49, 28, 109, 9, 185, 105, 95, 1, 131, 159, 272, 36, 67, 86, 254, 39, 55, 35, 0, 505, 31, 83, 169, 208, 327, 286, 98, 168, 535, 312, 708}, - {5, 1, 2, 21, 0, 12, 48, 22, 10, 14, 36, 3, 32, 17, 23, 54, 86, 38, 4, 51, 13, 37, 137, 50, 65, 281, 114, 45, 28, 99, 58, 202}, - {141, 269, 352, 82, 217, 351, 180, 854, 372, 922, 752, 1, 15, 260, 317, 318, 515, 202, 64, 700, 120, 349, 954, 753, 77, 35, 67, 717, 898, 137, 365, 115}, - {144, 203, 613, 418, 326, 406, 96, 669, 137, 679, 1, 228, 494, 822, 840, 317, 36, 83, 855, 160, 817, 859, 856, 816, 217, 831, 345, 93, 876, 77, 44, 251}, - {15, 13, 515, 23, 700, 753, 51, 1, 33, 0, 202, 21, 2, 5, 180, 141, 120, 165, 217, 82, 12, 117, 4, 352, 269, 197, 115, 32, 3, 9, 134, 260}, - {13, 23, 115, 1, 0, 51, 4, 77, 2, 33, 15, 141, 10, 5, 341, 180, 515, 3, 217, 202, 9, 365, 317, 64, 700, 102, 11, 165, 197, 22, 753, 7}, - {531, 943, 373, 160, 728, 93, 206, 260, 261, 559, 964, 269, 717, 535, 332, 384, - 365, 295, 110, 533, 141, 10, 180, 352, 244, 137, 120, 55, 959, 564, 36, 253}, - {1, 31, 36, 170, 22, 55, 44, 10, 86, 64, 127, 0, 2, 98, 301, 164, 740, 338, 237, 143, 5, 125, 116, 13, 242, 141, 299, 180, 23, 169, 105, 12}, - {13, 23, 141, 77, 51, 4, 64, 32, 33, 202, 115, 269, 102, 128, 21, 0, 177, 180, 318, 90, 40, 10, 7, 5, 137, 15, 217, 352, 9, 291, 59, 22}, - {202, 120, 260, 318, 77, 15, 450, 269, 1, 82, 33, 23, 141, 13, 51, 515, 351, 128, 700, 5, 64, 326, 137, 21, 102, 110, 753, 494, 93, 523, 817, 165}, - {523, 899, 102, 33, 730, 15, 23, 403, 719, 117, 153, 13, 515, 51, 475, 4, 700, 5, 453, 817, 196, 753, 494, 40, 202, 120, 1, 2, 450, 457, 17, 421}, - {202, 403, 494, 450, 120, 817, 523, 475, 318, 453, 33, 402, 128, 77, 13, 51, 260, 576, 342, 102, 15, 23, 515, 4, 700, 5, 82, 753, 326, 210, 137, 615}, - {2, 29, 112, 66, 7, 52, 70, 151, 58, 87, 135, 5, 74, 226, 307, 6, 14, 186, 1, 45, 549, 172, 644, 25, 113, 287, 46, 155, 334, 64, 294, 97}, - {1, 77, 349, 291, 260, 120, 652, 102, 5, 39, 64, 269, 9, 33, 340, 342, 13, 98, 888, 698, 23, 296, 100, 318, 51, 202, 87, 137, 638, 128, 50, 850}, - {1, 13, 15, 2, 0, 4, 23, 515, 5, 141, 180, 3, 700, 341, 115, 51, 753, 269, 77, 901, 197, 352, 217, 33, 21, 11, 365, 6, 165, 202, 7, 317}, - {7, 14, 16, 2, 46, 5, 70, 58, 1, 38, 24, 35, 92, 163, 0, 75, 21, 18, 50, 54, 140, 12, 87, 220, 155, 69, 171, 23, 60, 9, 13, 307}, - {2, 29, 66, 226, 135, 7, 87, 74, 52, 278, 6, 75, 222, 220, 294, 70, 97, 1, 145, 25, 172, 262, 324, 38, 69, 112, 331, 92, 5, 14, 140, 26}, - {15, 515, 700, 753, 33, 77, 117, 4, 1, 102, 134, 40, 153, 11, 13, 196, 217, 21, 5, 51, 23, 115, 32, 3, 2, 202, 141, 137, 128, 291, 48, 177}, - {15, 217, 82, 515, 351, 141, 317, 1, 13, 700, 260, 77, 110, 120, 115, 854, 23, 753, 180, 51, 21, 36, 137, 922, 5, 64, 365, 352, 291, 202, 93, 341}, - {31, 190, 30, 373, 120, 110, 863, 88, 44, 127, 908, 856, 260, 318, 82, 98, 93, 187, 836, 717, 935, 39, 442, 131, 141, 254, 228, 219, 1, 968, 77, 116}, - {23, 13, 308, 9, 165, 115, 51, 21, 401, 125, 49, 39, 197, 391, 159, 254, 217, 743, 28, 438, 773, 629, 558, 386, 341, 95, 32, 317, 876, 679, 109, 166}, - {49, 5, 43, 165, 7, 0, 21, 104, 125, 22, 173, 422, 64, 13, 623, 102, 20, 18, 314, 95, 91, 141, 23, 31, 193, 51, 391, 900, 779, 558, 92, 232}, - {1, 4, 13, 2, 15, 0, 23, 515, 77, 3, 341, 33, 5, 700, 115, 51, 202, 753, 141, 180, 11, 10, 102, 217, 6, 901, 40, 7, 197, 318, 317, 365}, - {93, 843, 295, 120, 36, 160, 206, 261, 10, 137, 567, 110, 384, 141, 943, 268, 201, 332, 258, 55, 1, 180, 64, 116, 44, 144, 699, 203, 282, 31, 260, 373}, - {81, 7, 192, 426, 43, 173, 172, 104, 879, 91, 5, 712, 715, 526, 6, 97, 568, 95, 448, 66, 33, 861, 560, 32, 49, 20, 0, 636, 232, 825, 2, 22}, - {475, 403, 51, 453, 33, 102, 13, 23, 494, 202, 0, 196, 15, 77, 153, 18, 4, 117, 515, 450, 318, 22, 730, 128, 700, 421, 65, 753, 269, 402, 134, 817}, - {141, 269, 260, 318, 202, 120, 352, 349, 82, 351, 1, 5, 854, 137, 64, 291, 15, 922, 180, 851, 32, 77, 515, 372, 21, 700, 7, 217, 13, 947, 33, 753}, - {15, 515, 700, 753, 1, 13, 0, 2, 4, 23, 3, 5, 180, 115, 197, 12, 51, 165, 217, 10, 961, 9, 6, 141, 352, 21, 8, 7, 33, 77, 457, 120}, - {39, 166, 9, 30, 0, 101, 274, 404, 252, 333, 190, 100, 158, 438, 310, 88, 68, 265, 656, 21, 1, 530, 329, 344, 49, 539, 625, 254, 13, 131, 48, 419}, - {0, 1, 28, 9, 22, 12, 65, 83, 67, 36, 5, 2, 50, 55, 96, 109, 16, 13, 24, 23, 21, 238, 49, 18, 285, 160, 128, 39, 69, 114, 7, 323}, - {15, 515, 700, 1, 0, 753, 23, 2, 13, 51, 5, 180, 115, 6, 3, 9, 197, 12, 457, 120, 7, 165, 901, 82, 4, 21, 8, 141, 31, 33, 719, 341}, - {9, 39, 30, 0, 28, 166, 22, 49, 180, 1, 352, 35, 317, 158, 88, 141, 498, 131, 115, 345, 752, 128, 228, 217, 100, 83, 219, 930, 13, 251, 365, 36}, - {5, 61, 45, 2, 80, 29, 311, 209, 6, 17, 58, 1, 151, 106, 454, 667, 243, 70, 52, 496, 287, 592, 255, 738, 64, 74, 483, 14, 27, 32, 112, 19}, - {31, 125, 22, 44, 299, 456, 685, 242, 599, 116, 170, 28, 0, 1, 492, 393, 506, 144, 558, 10, 268, 301, 239, 23, 13, 36, 963, 367, 55, 206, 105, 95}, - {187, 258, 926, 574, 839, 93, 228, 860, 406, 219, 871, 160, 137, 531, 224, 116, 120, 902, 669, 201, 36, 131, 44, 144, 843, 533, 318, 384, 442, 1, 434, 268}, - {7, 107, 75, 16, 87, 9, 64, 177, 24, 18, 291, 77, 349, 141, 60, 232, 23, 0, 51, 269, 132, 14, 5, 21, 70, 32, 678, 112, 126, 121, 71, 947}, - {15, 515, 700, 753, 1, 0, 2, 13, 5, 3, 23, 180, 4, 115, 901, 51, 6, 8, 961, 9, 7, 10, 12, 82, 197, 22, 141, 341, 33, 120, 365, 457}, - {13, 23, 51, 1, 5, 202, 2, 12, 15, 21, 165, 141, 0, 115, 3, 4, 32, 515, 197, 10, 180, 318, 128, 120, 64, 700, 6, 7, 403, 269, 457, 137}, - {1, 2, 0, 77, 64, 3, 141, 13, 33, 15, 23, 10, 6, 102, 5, 515, 180, 4, 117, 7, 700, 165, 11, 217, 269, 40, 753, 115, 128, 17, 197, 134}, - {345, 531, 332, 269, 260, 317, 717, 752, 373, 351, 180, 352, 728, 82, 10, 365, 160, 533, 217, 143, 498, 251, 244, 93, 341, 901, 36, 1, 141, 898, 55, 864}, - {16, 7, 33, 189, 92, 77, 388, 60, 140, 35, 102, 24, 14, 1, 230, 21, 150, 117, 733, 314, 18, 915, 71, 13, 108, 134, 5, 64, 69, 2, 98, 22}, - {142, 202, 234, 178, 5, 786, 77, 49, 70, 0, 416, 450, 639, 878, 1, 48, 21, 929, 147, 259, 315, 455, 198, 120, 12, 481, 163, 113, 846, 329, 318, 22}, - {81, 715, 192, 0, 173, 712, 681, 104, 636, 91, 74, 20, 750, 370, 7, 718, 95, 879, 22, 43, 825, 560, 422, 64, 207, 49, 172, 18, 397, 10, 426, 319}, - {13, 23, 15, 51, 515, 0, 700, 753, 4, 1, 961, 2, 10, 115, 457, 11, 33, 453, 3, 5, 9, 40, 12, 197, 165, 77, 401, 475, 64, 102, 22, 569}, - {64, 297, 5, 445, 95, 61, 250, 311, 80, 34, 17, 312, 45, 2, 86, 472, 58, 14, 180, 53, 22, 151, 869, 738, 247, 237, 29, 1, 128, 165, 21, 288}, - {16, 24, 18, 71, 7, 35, 118, 92, 14, 154, 60, 68, 0, 149, 28, 302, 124, 150, 55, 175, 2, 9, 97, 1, 429, 20, 108, 273, 22, 65, 43, 126}, - {195, 360, 156, 771, 132, 163, 626, 687, 591, 371, 883, 146, 121, 846, 70, 586, 379, 13, 293, 98, 407, 48, 761, 296, 354, 18, 31, 1, 55, 49, 21, 105}, - {202, 13, 77, 23, 318, 33, 51, 0, 4, 141, 5, 21, 217, 32, 291, 102, 64, 128, 15, 10, 9, 494, 269, 137, 515, 403, 1, 31, 117, 700, 120, 317}, - {7, 192, 97, 81, 172, 66, 426, 173, 43, 715, 712, 232, 861, 879, 104, 330, 568, 298, 74, 893, 885, 526, 387, 825, 92, 140, 91, 14, 636, 6, 5, 448}, - {2, 1, 14, 6, 67, 7, 65, 69, 24, 36, 66, 124, 108, 83, 38, 29, 22, 86, 0, 18, 484, 5, 28, 46, 12, 10, 25, 302, 150, 16, 650, 74}, - {33, 77, 13, 202, 102, 4, 0, 23, 128, 51, 141, 64, 318, 22, 403, 269, 137, 10, 15, 40, 494, 117, 32, 59, 11, 153, 1, 21, 177, 196, 515, 115}, - {269, 141, 318, 77, 349, 291, 217, 202, 33, 15, 372, 304, 515, 22, 102, 177, 351, 700, 352, 120, 5, 137, 10, 317, 260, 753, 64, 851, 854, 403, 49, 21}, - {6, 74, 66, 85, 138, 25, 87, 42, 135, 26, 226, 222, 280, 29, 75, 500, 220, 278, 792, 70, 19, 2, 1, 294, 204, 64, 32, 145, 853, 112, 52, 174}, - {9, 0, 105, 39, 16, 18, 1, 101, 272, 31, 127, 98, 24, 518, 333, 252, 310, 28, 68, 737, 846, 371, 158, 916, 938, 49, 30, 7, 286, 35, 301, 455}, - {2, 1, 14, 67, 24, 46, 83, 108, 69, 29, 38, 103, 114, 36, 6, 133, 18, 0, 28, 7, 65, 52, 236, 75, 50, 398, 5, 309, 135, 16, 278, 160}, - {22, 1, 28, 105, 49, 95, 0, 2, 67, 55, 36, 239, 168, 159, 65, 35, 14, 170, 320, 164, 9, 7, 10, 5, 114, 12, 83, 64, 194, 109, 24, 301}, - {7, 66, 172, 97, 92, 140, 232, 568, 298, 14, 192, 314, 16, 380, 135, 324, 2, 330, 74, 38, 357, 448, 126, 69, 35, 5, 107, 6, 387, 60, 204, 572}, - {2, 29, 1, 14, 5, 6, 46, 133, 114, 50, 52, 26, 218, 108, 19, 13, 366, 236, 27, 45, 70, 17, 58, 23, 86, 51, 137, 65, 112, 38, 25, 12}, - {6, 1, 74, 25, 2, 26, 29, 66, 42, 19, 75, 14, 388, 67, 108, 70, 52, 85, 103, 65, 38, 138, 357, 133, 114, 594, 324, 516, 603, 96, 309, 69}, - {22, 9, 28, 1, 36, 49, 109, 105, 86, 95, 131, 31, 169, 39, 0, 141, 272, 159, 44, 55, 98, 180, 13, 30, 185, 115, 83, 128, 352, 137, 64, 208}, - {203, 822, 326, 23, 77, 859, 403, 494, 576, 39, 473, 182, 33, 1, 691, 100, 18, 217, 13, 817, 411, 447, 363, 102, 93, 966, 96, 478, 291, 704, 310, 120}, - {15, 515, 700, 753, 33, 77, 117, 4, 102, 134, 115, 153, 13, 1, 40, 217, 11, 196, 341, 2, 5, 3, 23, 317, 365, 0, 21, 291, 32, 51, 12, 569}, - {15, 515, 700, 753, 13, 0, 23, 1, 8, 82, 51, 165, 197, 120, 180, 2, 9, 33, 4, 110, 5, 12, 10, 260, 351, 386, 141, 7, 457, 475, 93, 901}, - {1, 23, 13, 15, 51, 0, 21, 2, 515, 5, 141, 180, 120, 165, 700, 202, 197, 4, 753, 12, 33, 9, 7, 82, 115, 93, 3, 352, 260, 6, 110, 48}, - {15, 515, 700, 753, 0, 1, 2, 5, 3, 4, 8, 13, 180, 341, 10, 23, 7, 6, 9, 51, 77, 197, 961, 115, 165, 82, 120, 31, 22, 202, 457, 217}, - {559, 661, 922, 564, 141, 533, 10, 317, 373, 110, 143, 269, 244, 260, 332, 261, - 93, 642, 752, 295, 351, 876, 531, 843, 180, 206, 728, 384, 352, 1, 434, 120}, - {15, 515, 1, 0, 700, 2, 13, 23, 753, 5, 51, 180, 3, 165, 12, 6, 197, 115, 4, 9, 7, 21, 719, 8, 457, 82, 141, 120, 33, 22, 901, 10}, - {198, 234, 0, 325, 5, 77, 202, 416, 20, 147, 32, 43, 639, 315, 49, 61, 450, 455, 142, 21, 113, 230, 22, 318, 725, 342, 207, 13, 95, 904, 494, 10}, - {447, 264, 363, 9, 411, 676, 682, 1, 156, 664, 821, 478, 166, 354, 812, 39, 100, 905, 382, 897, 98, 18, 759, 404, 31, 101, 724, 5, 265, 223, 88, 13}, - {24, 14, 69, 16, 35, 18, 2, 7, 108, 189, 71, 67, 267, 149, 1, 46, 68, 83, 38, 140, 0, 236, 251, 9, 388, 60, 133, 103, 65, 28, 29, 50}, - {16, 7, 35, 20, 14, 18, 109, 2, 43, 120, 107, 60, 1, 121, 326, 907, 553, 77, 13, 147, 23, 82, 68, 260, 0, 403, 5, 24, 202, 126, 265, 199}, - {30, 131, 187, 276, 31, 44, 613, 442, 39, 9, 190, 228, 1, 839, 116, 935, 908, 219, 127, 88, 244, 224, 110, 137, 93, 201, 98, 141, 36, 567, 0, 856}, - {98, 223, 1, 393, 812, 265, 100, 421, 593, 834, 697, 48, 51, 410, 791, 382, 21, 88, 31, 284, 9, 125, 96, 293, 230, 23, 213, 217, 656, 689, 541, 5}, - {98, 51, 127, 219, 616, 258, 105, 293, 395, 421, 924, 512, 31, 308, 23, 201, 116, 44, 301, 272, 763, 276, 125, 13, 453, 170, 401, 295, 261, 944, 115, 567}, - {253, 110, 951, 352, 811, 206, 332, 180, 141, 244, 282, 10, 854, 417, 642, 638, - 559, 752, 143, 911, 260, 55, 93, 533, 499, 498, 661, 120, 351, 959, 564, 341}, - {49, 9, 159, 254, 272, 158, 0, 131, 28, 39, 627, 105, 327, 286, 22, 518, 688, 578, 68, 347, 374, 101, 224, 424, 95, 35, 219, 24, 16, 364, 65, 344}, - {105, 22, 131, 272, 98, 286, 327, 109, 374, 239, 28, 95, 320, 219, 9, 224, 55, 127, 187, 36, 578, 169, 64, 185, 538, 1, 159, 10, 371, 634, 49, 616}, - {691, 478, 340, 1, 658, 914, 724, 363, 744, 698, 156, 772, 411, 296, 682, 447, 9, 284, 335, 98, 264, 303, 909, 21, 354, 410, 225, 13, 664, 686, 88, 919}, - {16, 24, 35, 18, 71, 7, 140, 108, 189, 267, 92, 60, 14, 230, 68, 69, 9, 1, 149, 46, 246, 191, 388, 167, 2, 0, 118, 236, 133, 21, 674, 5}, - {9, 0, 127, 31, 98, 371, 395, 39, 737, 49, 1, 44, 385, 272, 512, 28, 293, 242, 836, 761, 254, 299, 101, 16, 187, 22, 116, 158, 159, 131, 18, 21}, - {16, 18, 68, 0, 60, 35, 9, 101, 252, 28, 118, 24, 419, 55, 7, 109, 604, 71, 39, 121, 22, 364, 14, 158, 191, 167, 925, 126, 329, 21, 92, 49}, - {116, 268, 203, 93, 206, 692, 551, 31, 417, 940, 499, 8, 473, 44, 202, 523, 959, 0, 120, 137, 559, 22, 450, 403, 576, 10, 728, 299, 13, 326, 51, 1}, - {225, 459, 744, 1, 919, 914, 691, 330, 622, 21, 141, 223, 5, 284, 934, 335, 88, 538, 340, 82, 385, 839, 363, 120, 478, 98, 48, 30, 64, 32, 686, 166}, - {5, 1, 2, 0, 14, 36, 21, 281, 12, 48, 50, 67, 22, 28, 54, 83, 24, 218, 38, 10, 181, 9, 32, 18, 65, 58, 45, 114, 430, 17, 99, 37}, - {137, 450, 202, 704, 120, 260, 326, 318, 968, 269, 851, 403, 291, 77, 23, 141, 182, 310, 494, 373, 351, 457, 82, 890, 349, 110, 60, 128, 817, 678, 105, 96}, - {15, 515, 700, 753, 4, 33, 13, 23, 77, 5, 40, 11, 102, 93, 1, 21, 110, 51, 82, 117, 141, 2, 10, 8, 32, 64, 120, 31, 202, 3, 217, 115}, - {15, 13, 1, 23, 515, 0, 51, 2, 700, 5, 753, 21, 180, 141, 165, 3, 12, 115, 197, 4, 7, 6, 457, 9, 352, 202, 33, 8, 719, 120, 77, 341}, - {219, 127, 258, 98, 276, 201, 131, 395, 944, 293, 116, 284, 567, 31, 242, 105, 137, 935, 295, 44, 403, 860, 51, 224, 576, 456, 9, 371, 578, 475, 202, 512}, - {16, 7, 18, 35, 60, 0, 14, 20, 118, 28, 68, 22, 2, 24, 1, 92, 158, 107, 5, 49, 154, 126, 109, 12, 43, 10, 55, 6, 677, 71, 21, 168}, - {93, 728, 531, 160, 559, 373, 574, 120, 295, 860, 533, 269, 717, 260, 926, 902, - 258, 318, 36, 201, 261, 434, 851, 137, 617, 141, 187, 352, 843, 384, 332, 251}, - {28, 0, 1, 9, 22, 109, 83, 39, 49, 12, 36, 67, 55, 5, 96, 2, 128, 30, 158, 69, 21, 23, 160, 208, 35, 13, 65, 323, 50, 141, 194, 238}, - {23, 13, 51, 1, 5, 15, 141, 21, 0, 2, 165, 515, 202, 700, 12, 197, 180, 120, 32, 115, 4, 753, 64, 9, 7, 269, 6, 3, 125, 386, 48, 453}, - {5, 21, 13, 49, 14, 20, 7, 23, 43, 32, 1, 0, 652, 48, 713, 22, 38, 2, 16, 132, 955, 107, 12, 279, 24, 888, 197, 640, 70, 303, 18, 638}, - {9, 0, 28, 39, 1, 30, 35, 101, 22, 67, 83, 141, 49, 175, 36, 68, 55, 88, 13, 251, 10, 69, 23, 158, 180, 115, 64, 100, 217, 65, 345, 166}, - {260, 120, 82, 269, 5, 450, 351, 1, 202, 141, 854, 13, 77, 922, 32, 33, 137, 4, 23, 125, 291, 21, 15, 515, 165, 349, 177, 700, 318, 326, 180, 753}, - {121, 16, 18, 35, 363, 101, 60, 20, 107, 14, 68, 259, 621, 55, 604, 43, 7, 252, 9, 364, 126, 0, 167, 191, 5, 407, 132, 28, 199, 419, 146, 10}, - {13, 23, 51, 1, 15, 0, 2, 141, 5, 515, 12, 21, 700, 115, 165, 180, 4, 753, 3, 197, 202, 32, 9, 120, 7, 8, 6, 11, 37, 10, 457, 269}, - {201, 144, 206, 443, 418, 203, 435, 96, 335, 459, 187, 1, 88, 332, 330, 321, 269, 934, 30, 372, 822, 521, 268, 326, 44, 523, 382, 141, 410, 264, 494, 473}, - {31, 44, 276, 201, 116, 131, 284, 662, 567, 144, 9, 489, 98, 295, 268, 434, 0, 30, 137, 39, 93, 1, 187, 22, 219, 918, 110, 299, 141, 36, 224, 384}, - {520, 478, 664, 1, 264, 604, 9, 167, 777, 759, 411, 0, 806, 724, 48, 21, 101, 68, 647, 936, 363, 223, 118, 682, 410, 18, 100, 16, 252, 98, 265, 13}, - {23, 70, 21, 87, 60, 75, 120, 182, 163, 379, 92, 18, 7, 937, 71, 121, 446, 132, 24, 98, 931, 126, 107, 77, 795, 195, 115, 44, 411, 146, 51, 850}, - {39, 9, 0, 737, 127, 31, 846, 98, 1, 827, 105, 310, 371, 30, 254, 100, 44, 18, 395, 242, 272, 101, 385, 916, 836, 16, 265, 131, 938, 93, 166, 557}, - {279, 20, 43, 126, 107, 7, 92, 16, 356, 362, 60, 595, 246, 359, 598, 35, 0, 683, 939, 653, 121, 97, 125, 441, 399, 392, 150, 199, 48, 230, 14, 649}, - {206, 417, 93, 959, 499, 728, 8, 559, 120, 473, 137, 141, 10, 564, 31, 260, 44, 450, 203, 341, 253, 244, 373, 116, 143, 638, 268, 180, 352, 110, 318, 940}, - {259, 465, 147, 132, 590, 687, 534, 199, 581, 146, 941, 427, 107, 640, 279, 178, 121, 5, 195, 150, 522, 955, 198, 35, 786, 929, 798, 142, 1, 21, 325, 626}, - {523, 15, 120, 450, 202, 515, 403, 51, 817, 700, 13, 753, 23, 457, 33, 899, 128, 64, 730, 102, 494, 342, 115, 719, 453, 196, 49, 99, 318, 421, 308, 5}, - {141, 559, 10, 244, 365, 564, 661, 180, 253, 143, 752, 110, 55, 317, 533, 341, 901, 93, 373, 206, 535, 160, 82, 922, 260, 36, 531, 964, 352, 332, 261, 197}, - {219, 258, 98, 127, 276, 964, 943, 137, 843, 535, 201, 935, 131, 860, 261, 295, 284, 567, 206, 44, 116, 31, 253, 492, 203, 332, 160, 615, 36, 93, 55, 692}, - {0, 319, 422, 207, 945, 693, 577, 887, 32, 804, 95, 344, 104, 904, 61, 20, 5, 43, 7, 725, 113, 510, 306, 102, 49, 263, 153, 426, 33, 83, 22, 9}, - {1, 22, 0, 5, 12, 2, 36, 21, 28, 86, 49, 105, 9, 10, 23, 13, 141, 95, 31, 55, 128, 37, 51, 4, 83, 202, 3, 64, 96, 7, 32, 44}, - {15, 515, 13, 700, 1, 0, 753, 2, 23, 3, 4, 5, 51, 10, 115, 197, 6, 33, 12, 9, 165, 7, 8, 77, 11, 961, 180, 269, 141, 22, 120, 457}, - {15, 1, 23, 120, 77, 13, 515, 51, 141, 202, 700, 180, 110, 137, 260, 753, 326, 5, 128, 102, 0, 21, 2, 165, 269, 33, 197, 450, 318, 217, 93, 115}, - {15, 515, 1, 700, 0, 753, 13, 2, 23, 180, 51, 5, 120, 4, 9, 115, 197, 12, 7, 165, 21, 33, 6, 82, 3, 8, 523, 901, 31, 141, 457, 260}, - {16, 18, 24, 7, 92, 35, 60, 75, 9, 13, 71, 14, 0, 108, 50, 21, 126, 121, 1, 140, 23, 5, 132, 146, 2, 12, 128, 10, 64, 141, 70, 87}, - {180, 341, 901, 15, 515, 1, 365, 700, 0, 2, 197, 753, 115, 4, 10, 13, 752, 5, 3, 8, 165, 317, 141, 23, 143, 873, 44, 31, 569, 55, 93, 6}, - {9, 0, 175, 35, 101, 28, 39, 67, 68, 1, 65, 83, 30, 69, 364, 336, 22, 114, 55, 124, 194, 158, 100, 289, 252, 166, 64, 345, 103, 36, 50, 88}, - {64, 165, 180, 197, 115, 247, 217, 237, 21, 13, 32, 316, 22, 141, 352, 72, 288, 304, 95, 225, 76, 391, 386, 16, 468, 90, 49, 35, 365, 640, 372, 23}, - {15, 515, 700, 13, 753, 1, 0, 2, 23, 4, 5, 3, 115, 51, 141, 197, 12, 10, 180, 961, 7, 9, 21, 33, 217, 6, 8, 165, 457, 11, 77, 341}, - {132, 121, 199, 146, 60, 279, 493, 640, 407, 598, 126, 195, 534, 581, 955, 590, 107, 5, 150, 35, 522, 49, 259, 16, 18, 360, 156, 0, 147, 362, 21, 167}, - {0, 1, 28, 9, 22, 5, 36, 12, 65, 24, 67, 96, 2, 83, 18, 50, 114, 55, 21, 16, 7, 10, 23, 14, 13, 160, 137, 51, 48, 218, 103, 69}, - {93, 120, 957, 77, 30, 968, 459, 110, 137, 160, 613, 102, 202, 352, 373, 141, 31, 372, 217, 330, 190, 318, 269, 260, 203, 44, 28, 473, 228, 177, 863, 704}, - {15, 515, 700, 0, 753, 1, 13, 23, 2, 51, 5, 9, 120, 82, 4, 7, 901, 197, 10, 8, 260, 180, 341, 12, 33, 6, 3, 523, 165, 102, 115, 141}, - {206, 417, 8, 141, 499, 44, 244, 93, 31, 10, 137, 253, 559, 116, 728, 144, 120, 564, 269, 638, 203, 352, 143, 260, 341, 752, 268, 717, 951, 180, 160, 110}, - {530, 254, 228, 1, 96, 21, 406, 39, 827, 31, 669, 840, 613, 829, 137, 679, 166, 98, 23, 51, 960, 438, 131, 93, 48, 224, 219, 317, 310, 36, 876, 190}, - {15, 515, 700, 753, 13, 457, 0, 197, 719, 1, 165, 82, 23, 8, 120, 730, 2, 10, 12, 180, 134, 5, 9, 141, 260, 4, 351, 51, 115, 3, 341, 899}, - {0, 16, 68, 9, 24, 28, 18, 35, 252, 109, 39, 419, 124, 158, 154, 55, 101, 71, 22, 118, 60, 7, 49, 65, 333, 14, 1, 10, 329, 364, 677, 346}, - {1, 15, 13, 23, 515, 51, 120, 0, 700, 180, 2, 165, 5, 753, 141, 197, 21, 33, 202, 102, 260, 4, 9, 12, 7, 326, 137, 450, 115, 6, 82, 110}, - {535, 253, 352, 564, 110, 365, 82, 180, 341, 10, 854, 533, 55, 898, 244, 901, - 873, 141, 752, 143, 642, 559, 498, 317, 36, 951, 115, 964, 638, 282, 661, 197}, - {31, 44, 125, 338, 116, 64, 242, 36, 1, 10, 55, 22, 456, 237, 180, 13, 299, 164, 506, 86, 23, 165, 558, 143, 0, 762, 492, 479, 844, 546, 93, 8}, - {13, 23, 4, 1, 202, 2, 0, 51, 115, 77, 141, 180, 5, 15, 217, 3, 33, 11, 515, 317, 9, 10, 102, 21, 700, 341, 365, 318, 269, 64, 32, 128}, - {9, 39, 0, 166, 68, 101, 28, 364, 30, 158, 562, 35, 175, 65, 333, 154, 49, 404, 706, 124, 21, 252, 274, 168, 190, 289, 100, 570, 16, 1, 310, 346}, - {15, 515, 700, 753, 341, 13, 0, 23, 1, 33, 141, 4, 260, 82, 77, 51, 351, 180, 9, 5, 115, 137, 10, 217, 11, 120, 102, 40, 349, 269, 202, 854} -#else -#include "Table4.h" -#endif -}}; -// endregion - template class OrderTable<3>; template class OrderTable<4>; diff --git a/src/rgbcx/BC1/Table4.h b/src/rgbcx/BC1/OrderTable4.cpp similarity index 76% rename from src/rgbcx/BC1/Table4.h rename to src/rgbcx/BC1/OrderTable4.cpp index cda3f0a..061528e 100644 --- a/src/rgbcx/BC1/Table4.h +++ b/src/rgbcx/BC1/OrderTable4.cpp @@ -1,3 +1,1000 @@ +/* Python-rgbcx Texture Compression Library + Copyright (C) 2021 Andrew Cassidy + Partially derived from rgbcx.h written by Richard Geldreich + and licenced under the public domain + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . + */ + +#include "OrderTable.h" + +// clang-format off +namespace rgbcx::BC1 { + +template <> +const OrderTable<4>::BestOrderArray OrderTable<4>::BestOrders = {{ +#if RGBCX_USE_SMALLER_TABLES +{202, 120, 13, 318, 15, 23, 403, 450, 5, 51, 260, 128, 77, 21, 33, 494, 515, 523, 4, 141, 269, 1, 2, 700, 137, 49, 48, 102, 7, 64, 753, 82}, +{13, 141, 23, 217, 115, 51, 77, 2, 64, 21, 0, 4, 5, 317, 137, 269, 202, 33, 318, 7, 291, 352, 9, 10, 3, 180, 32, 6, 365, 102, 341, 349}, +{29, 58, 262, 1, 52, 74, 6, 171, 5, 287, 151, 334, 27, 500, 75, 26, 331, 223, 53, 635, 220, 19, 50, 45, 46, 17, 14, 396, 163, 409, 324, 70}, +{40, 51, 33, 453, 14, 23, 62, 56, 12, 196, 730, 475, 153, 99, 403, 775, 117, 130, 585, 34, 4, 17, 162, 11, 139, 57, 102, 38, 108, 47, 123, 440}, +{33, 23, 51, 13, 102, 64, 202, 128, 12, 40, 15, 196, 153, 10, 1, 2, 77, 99, 141, 0, 515, 5, 117, 3, 120, 403, 700, 165, 22, 14, 269, 453}, +{13, 23, 51, 4, 77, 141, 202, 33, 115, 64, 32, 128, 0, 11, 177, 40, 15, 102, 2, 217, 7, 137, 269, 21, 90, 59, 515, 1, 180, 403, 22, 6}, +{26, 235, 19, 47, 648, 624, 78, 145, 27, 112, 122, 64, 444, 6, 630, 453, 25, 42, 65, 130, 711, 85, 390, 113, 416, 108, 665, 29, 730, 138, 644, 95}, +{64, 141, 352, 751, 217, 247, 237, 437, 177, 269, 86, 954, 947, 875, 32, 318, 95, 77, 304, 92, 597, 180, 232, 291, 128, 864, 349, 588, 372, 202, 312, 1}, +{642, 898, 180, 638, 901, 341, 82, 197, 10, 951, 15, 515, 165, 762, 700, 253, 811, 753, 752, 365, 143, 479, 244, 569, 8, 110, 351, 873, 55, 31, 499, 116}, +{221, 23, 51, 125, 438, 254, 13, 21, 39, 49, 308, 656, 0, 115, 530, 159, 158, 401, 30, 166, 912, 386, 165, 688, 518, 9, 105, 627, 424, 22, 421, 33}, +{143, 31, 1, 44, 197, 8, 180, 125, 116, 55, 13, 498, 23, 341, 638, 242, 93, 15, 2, 141, 0, 901, 752, 115, 36, 206, 165, 479, 338, 365, 515, 762}, +{12, 23, 51, 13, 14, 15, 37, 99, 515, 38, 700, 117, 2, 196, 134, 153, 753, 64, 54, 33, 128, 120, 21, 0, 328, 5, 139, 82, 453, 719, 457, 1}, +{13, 15, 23, 515, 961, 700, 457, 753, 51, 115, 4, 165, 197, 2, 38, 569, 1, 474, 0, 37, 99, 719, 5, 12, 629, 14, 11, 3, 33, 77, 64, 10}, +{15, 515, 700, 753, 1, 0, 2, 4, 3, 23, 134, 12, 961, 5, 10, 197, 11, 33, 82, 120, 457, 51, 165, 7, 6, 341, 217, 21, 77, 9, 40, 180}, +{13, 51, 23, 457, 719, 961, 730, 401, 165, 453, 0, 117, 386, 15, 134, 1, 758, 153, 12, 54, 515, 99, 11, 2, 700, 5, 753, 4, 308, 33, 6, 899}, +{134, 898, 82, 117, 13, 33, 77, 102, 23, 260, 341, 351, 120, 901, 197, 153, 961, 111, 196, 110, 180, 457, 854, 10, 450, 8, 165, 40, 4, 115, 0, 365}, +{60, 18, 126, 167, 35, 16, 191, 71, 24, 92, 121, 271, 68, 107, 212, 146, 118, 150, 199, 7, 21, 1, 9, 575, 727, 5, 566, 48, 0, 132, 108, 273}, +{62, 136, 129, 123, 128, 41, 162, 17, 249, 211, 214, 789, 618, 710, 38, 678, 248, 507, 57, 64, 152, 269, 119, 3, 177, 183, 597, 106, 4, 179, 216, 90}, +{403, 523, 51, 475, 494, 453, 817, 899, 202, 23, 450, 13, 421, 120, 102, 730, 33, 128, 4, 1, 805, 5, 7, 153, 757, 260, 318, 196, 77, 457, 326, 65}, +{4, 59, 3, 62, 12, 33, 56, 193, 27, 21, 102, 17, 40, 77, 76, 84, 32, 0, 6, 123, 119, 177, 128, 11, 18, 611, 605, 25, 13, 51, 73, 210}, +{43, 20, 319, 422, 414, 945, 0, 7, 819, 61, 5, 376, 325, 173, 804, 904, 470, 693, 97, 707, 14, 49, 22, 104, 147, 107, 95, 32, 426, 1, 330, 577}, +{13, 23, 51, 2, 0, 115, 4, 141, 217, 33, 10, 77, 1, 15, 64, 180, 3, 515, 7, 6, 22, 102, 11, 5, 40, 9, 165, 700, 202, 197, 317, 341}, +{28, 49, 0, 105, 1, 24, 65, 159, 35, 55, 95, 239, 16, 2, 109, 7, 9, 14, 170, 320, 347, 168, 424, 158, 10, 301, 124, 5, 67, 21, 64, 36}, +{15, 515, 700, 753, 0, 1, 13, 2, 117, 4, 12, 10, 5, 165, 457, 3, 9, 134, 11, 7, 6, 51, 77, 64, 961, 82, 33, 197, 14, 341, 120, 141}, +{7, 71, 14, 149, 97, 18, 60, 16, 150, 92, 398, 189, 140, 124, 24, 273, 35, 2, 69, 302, 154, 68, 0, 336, 517, 43, 66, 28, 118, 251, 230, 1}, +{4, 102, 33, 77, 40, 59, 11, 624, 210, 12, 128, 342, 5, 503, 91, 139, 64, 32, 25, 494, 202, 678, 416, 0, 403, 275, 21, 450, 196, 318, 523, 177}, +{25, 19, 42, 6, 122, 813, 256, 235, 85, 26, 436, 53, 297, 573, 680, 390, 445, 63, 27, 416, 80, 233, 65, 73, 389, 283, 45, 605, 194, 17, 250, 343}, +{402, 102, 202, 128, 33, 300, 403, 23, 12, 77, 40, 21, 342, 117, 483, 99, 25, 494, 6, 4, 63, 32, 84, 569, 139, 757, 475, 318, 19, 26, 196, 134}, +{158, 9, 0, 109, 39, 49, 65, 22, 35, 168, 55, 24, 68, 124, 159, 16, 185, 344, 333, 154, 254, 272, 175, 289, 1, 577, 95, 28, 105, 810, 30, 169}, +{197, 180, 115, 237, 498, 165, 2, 5, 287, 546, 400, 3, 61, 34, 509, 13, 297, 80, 341, 52, 45, 186, 58, 881, 23, 873, 468, 176, 64, 17, 311, 250}, +{120, 968, 373, 260, 704, 110, 450, 202, 137, 318, 77, 95, 269, 326, 217, 717, 661, 652, 851, 349, 93, 1, 518, 98, 827, 291, 21, 177, 82, 33, 848, 719}, +{44, 116, 144, 268, 434, 489, 367, 384, 98, 127, 918, 93, 948, 31, 206, 940, 855, 0, 203, 137, 9, 22, 617, 141, 332, 105, 393, 492, 959, 282, 299, 131}, +{13, 77, 23, 33, 51, 0, 64, 141, 102, 4, 2, 115, 1, 6, 202, 15, 10, 128, 269, 7, 177, 180, 3, 40, 22, 11, 515, 217, 117, 318, 700, 137}, +{15, 515, 700, 753, 4, 11, 141, 40, 165, 23, 64, 180, 13, 202, 32, 3, 51, 125, 5, 197, 21, 128, 0, 93, 77, 1, 120, 82, 269, 117, 110, 59}, +{176, 231, 585, 62, 34, 14, 412, 161, 56, 236, 527, 57, 17, 3, 51, 202, 4, 23, 369, 283, 128, 13, 472, 440, 84, 361, 136, 457, 381, 130, 719, 53}, +{9, 0, 180, 217, 237, 101, 141, 352, 88, 100, 230, 64, 175, 317, 115, 498, 68, 39, 30, 1, 702, 83, 213, 36, 365, 208, 752, 13, 252, 321, 952, 546}, +{28, 9, 22, 1, 49, 0, 109, 39, 83, 95, 86, 30, 13, 105, 128, 55, 141, 168, 158, 67, 31, 159, 208, 12, 96, 5, 185, 2, 160, 64, 137, 23}, +{72, 4, 38, 12, 51, 89, 477, 11, 57, 76, 401, 308, 23, 474, 99, 148, 413, 179, 59, 13, 431, 152, 54, 569, 17, 3, 205, 629, 197, 421, 405, 15}, +{457, 13, 23, 961, 15, 51, 515, 700, 165, 12, 753, 629, 11, 1, 719, 117, 0, 3, 2, 37, 569, 197, 40, 328, 33, 5, 153, 134, 99, 64, 38, 196}, +{254, 100, 310, 9, 30, 1, 39, 625, 166, 265, 190, 0, 272, 557, 131, 731, 31, 98, 578, 688, 404, 93, 101, 88, 49, 21, 127, 264, 44, 36, 252, 478}, +{51, 23, 12, 13, 15, 128, 99, 120, 10, 202, 515, 153, 64, 82, 700, 33, 165, 2, 5, 117, 403, 1, 141, 0, 3, 196, 37, 453, 753, 197, 260, 93}, +{38, 99, 542, 139, 453, 117, 196, 23, 457, 13, 328, 111, 37, 134, 961, 11, 12, 51, 40, 775, 587, 401, 474, 54, 153, 477, 41, 629, 33, 475, 14, 277}, +{6, 85, 25, 233, 343, 91, 26, 63, 138, 29, 19, 65, 283, 4, 81, 235, 42, 122, 605, 64, 648, 256, 174, 370, 74, 389, 718, 59, 45, 194, 445, 416}, +{49, 5, 97, 20, 197, 21, 18, 193, 0, 64, 408, 729, 173, 350, 43, 422, 165, 7, 14, 104, 61, 32, 509, 713, 523, 102, 120, 95, 125, 397, 35, 232}, +{144, 116, 268, 434, 384, 489, 367, 206, 93, 855, 940, 44, 98, 332, 617, 127, 959, 911, 137, 282, 203, 31, 22, 219, 141, 9, 131, 276, 417, 0, 1, 120}, +{17, 106, 64, 62, 32, 255, 136, 292, 476, 162, 129, 241, 123, 141, 41, 237, 720, 214, 209, 352, 519, 211, 186, 148, 752, 247, 507, 90, 21, 77, 197, 119}, +{2, 29, 52, 50, 5, 58, 14, 6, 27, 1, 366, 357, 45, 53, 17, 19, 171, 151, 26, 181, 133, 38, 218, 764, 287, 583, 61, 113, 3, 487, 600, 281}, +{130, 59, 196, 412, 381, 730, 711, 236, 77, 210, 202, 402, 453, 99, 401, 108, 361, 803, 291, 283, 153, 4, 57, 51, 128, 183, 14, 719, 503, 117, 23, 11}, +{13, 23, 51, 141, 77, 4, 33, 64, 115, 0, 217, 10, 180, 202, 2, 102, 11, 9, 15, 165, 40, 21, 128, 352, 22, 7, 197, 3, 317, 515, 269, 1}, +{23, 13, 202, 51, 120, 15, 21, 5, 141, 1, 128, 269, 137, 515, 64, 102, 125, 48, 98, 33, 260, 523, 318, 93, 700, 165, 450, 77, 2, 12, 403, 82}, +{1, 2, 14, 46, 29, 67, 38, 52, 5, 171, 58, 24, 103, 69, 96, 70, 83, 181, 54, 75, 163, 223, 16, 45, 112, 309, 155, 0, 186, 35, 18, 108}, +{15, 515, 700, 753, 13, 0, 1, 2, 153, 5, 23, 10, 117, 3, 9, 7, 134, 165, 12, 6, 341, 33, 4, 14, 77, 457, 115, 21, 719, 180, 217, 82}, +{197, 165, 509, 13, 391, 180, 308, 115, 23, 546, 5, 498, 2, 29, 3, 401, 901, 61, 34, 80, 14, 457, 250, 569, 237, 873, 38, 297, 45, 15, 468, 386}, +{19, 73, 27, 250, 200, 714, 444, 472, 26, 53, 34, 17, 813, 322, 283, 390, 128, 297, 78, 123, 432, 14, 436, 136, 106, 690, 57, 122, 389, 80, 503, 3}, +{3, 17, 21, 45, 62, 32, 38, 12, 155, 14, 2, 328, 5, 99, 401, 536, 828, 13, 227, 488, 106, 51, 719, 119, 540, 76, 165, 221, 115, 629, 209, 41}, +{115, 341, 873, 197, 365, 13, 901, 180, 569, 752, 317, 1, 10, 498, 143, 634, 261, 0, 509, 15, 943, 237, 44, 31, 116, 601, 165, 127, 282, 23, 141, 64}, +{453, 51, 23, 403, 33, 421, 475, 102, 15, 153, 196, 515, 13, 700, 117, 523, 12, 40, 753, 21, 4, 134, 0, 494, 670, 899, 22, 801, 730, 10, 11, 401}, +{23, 13, 51, 33, 12, 117, 153, 134, 453, 196, 15, 99, 515, 40, 14, 700, 128, 102, 11, 753, 77, 64, 403, 202, 0, 401, 475, 37, 65, 2, 3, 38}, +{2, 7, 5, 14, 70, 1, 29, 61, 52, 45, 6, 112, 66, 16, 21, 32, 592, 46, 38, 135, 87, 58, 186, 315, 290, 128, 113, 0, 64, 48, 227, 23}, +{33, 23, 102, 51, 128, 13, 64, 202, 141, 1, 77, 10, 153, 40, 196, 117, 2, 3, 0, 5, 15, 269, 403, 12, 137, 134, 318, 165, 120, 6, 453, 99}, +{16, 92, 7, 20, 43, 35, 126, 71, 60, 14, 107, 18, 68, 97, 0, 121, 279, 149, 24, 246, 191, 48, 118, 575, 55, 140, 362, 783, 230, 150, 375, 566}, +{13, 23, 4, 33, 77, 64, 51, 102, 141, 128, 32, 10, 0, 202, 40, 115, 59, 22, 90, 11, 177, 21, 291, 6, 7, 318, 180, 117, 137, 2, 95, 165}, +{507, 162, 129, 41, 4, 211, 62, 38, 123, 59, 57, 248, 183, 130, 99, 11, 3, 361, 202, 17, 402, 556, 266, 305, 803, 210, 128, 184, 152, 136, 313, 117}, +{643, 123, 193, 650, 802, 18, 25, 389, 718, 256, 65, 289, 84, 91, 619, 511, 415, 90, 235, 63, 57, 510, 324, 216, 862, 102, 6, 183, 108, 397, 217, 736}, +{13, 23, 15, 1, 515, 51, 0, 2, 700, 5, 753, 165, 141, 115, 12, 3, 4, 180, 21, 197, 457, 7, 6, 10, 120, 9, 33, 202, 77, 32, 8, 11}, +{23, 51, 13, 453, 64, 403, 12, 21, 5, 202, 128, 475, 165, 141, 523, 95, 125, 115, 3, 1, 4, 730, 120, 32, 2, 494, 180, 719, 457, 197, 450, 401}, +{204, 74, 135, 66, 6, 174, 192, 7, 138, 172, 85, 353, 348, 580, 280, 97, 95, 500, 29, 64, 426, 32, 87, 889, 65, 81, 25, 2, 52, 43, 568, 673}, +{35, 0, 68, 69, 24, 9, 1, 16, 65, 103, 149, 133, 18, 114, 28, 50, 83, 2, 189, 7, 46, 14, 101, 336, 175, 124, 251, 55, 71, 218, 38, 238}, +{16, 101, 0, 118, 9, 18, 24, 68, 35, 154, 71, 124, 60, 212, 191, 520, 55, 806, 694, 167, 28, 39, 364, 375, 1, 346, 252, 65, 604, 302, 22, 21}, +{0, 9, 16, 35, 1, 24, 68, 18, 65, 21, 103, 67, 13, 149, 28, 189, 71, 23, 101, 238, 114, 7, 335, 133, 486, 141, 22, 212, 48, 50, 30, 118}, +{13, 202, 23, 77, 33, 51, 128, 5, 21, 141, 115, 32, 102, 64, 4, 0, 318, 269, 10, 15, 291, 2, 494, 177, 11, 217, 3, 515, 22, 137, 6, 700}, +{16, 92, 60, 35, 7, 18, 24, 68, 150, 149, 14, 71, 0, 375, 97, 126, 118, 107, 230, 191, 246, 273, 140, 55, 175, 653, 9, 575, 2, 28, 566, 517}, +{76, 90, 21, 179, 316, 148, 205, 32, 464, 288, 184, 257, 245, 1, 89, 2, 460, 57, 152, 45, 38, 358, 645, 5, 12, 449, 350, 48, 37, 17, 4, 14}, +{19, 27, 26, 813, 80, 297, 17, 495, 436, 53, 73, 200, 4, 378, 250, 59, 106, 25, 45, 128, 361, 42, 113, 469, 122, 390, 77, 40, 736, 6, 11, 136}, +{6, 26, 235, 138, 19, 145, 112, 70, 331, 262, 25, 42, 52, 624, 27, 453, 122, 47, 500, 78, 648, 85, 29, 2, 630, 632, 409, 113, 50, 226, 108, 75}, +{7, 16, 14, 24, 92, 35, 18, 2, 46, 9, 60, 140, 0, 87, 50, 5, 54, 13, 12, 38, 171, 23, 126, 21, 58, 64, 1, 70, 128, 71, 220, 163}, +{90, 205, 257, 184, 32, 179, 460, 5, 245, 45, 2, 288, 769, 524, 57, 21, 152, 229, 17, 1, 497, 4, 292, 59, 619, 452, 432, 76, 476, 11, 266, 14}, +{15, 515, 700, 753, 4, 5, 11, 141, 13, 1, 33, 3, 0, 128, 202, 23, 180, 21, 2, 64, 269, 32, 117, 134, 120, 40, 102, 318, 153, 17, 137, 352}, +{47, 130, 711, 108, 453, 412, 730, 196, 390, 283, 78, 27, 51, 183, 381, 236, 128, 200, 719, 14, 153, 472, 503, 34, 59, 250, 3, 4, 57, 803, 123, 432}, +{12, 277, 51, 474, 111, 153, 23, 99, 13, 37, 961, 94, 629, 542, 569, 431, 79, 139, 38, 134, 117, 453, 33, 188, 196, 40, 115, 15, 11, 157, 401, 515}, +{17, 495, 469, 106, 26, 378, 80, 27, 161, 483, 19, 742, 527, 436, 383, 862, 73, 136, 53, 814, 297, 6, 119, 84, 62, 56, 25, 3, 209, 611, 4, 128}, +{81, 681, 636, 91, 0, 750, 370, 104, 718, 138, 18, 693, 173, 784, 29, 397, 348, 74, 192, 673, 174, 65, 6, 207, 64, 280, 306, 52, 671, 32, 355, 319}, +{15, 515, 700, 753, 33, 77, 4, 102, 115, 117, 40, 13, 1, 153, 134, 11, 5, 217, 23, 196, 2, 21, 3, 317, 32, 365, 0, 341, 291, 59, 12, 51}, +{0, 9, 28, 35, 68, 1, 65, 67, 101, 39, 69, 175, 16, 238, 13, 22, 96, 124, 18, 24, 251, 30, 55, 12, 23, 2, 50, 141, 114, 5, 154, 103}, +{23, 33, 77, 13, 117, 40, 11, 102, 64, 4, 51, 403, 153, 453, 10, 0, 196, 134, 128, 65, 12, 291, 86, 99, 95, 59, 15, 141, 202, 180, 137, 719}, +{214, 90, 289, 6, 874, 64, 25, 65, 235, 42, 751, 249, 256, 312, 194, 85, 746, 875, 174, 32, 525, 288, 519, 835, 247, 348, 233, 544, 217, 524, 437, 352}, +{1, 22, 2, 0, 36, 67, 28, 5, 49, 95, 12, 50, 168, 83, 105, 55, 7, 9, 14, 194, 103, 23, 114, 21, 584, 46, 10, 13, 38, 69, 208, 159}, +{269, 141, 13, 202, 33, 180, 318, 77, 291, 137, 102, 352, 128, 23, 349, 51, 31, 217, 372, 317, 125, 197, 44, 21, 11, 5, 901, 1, 18, 0, 4, 494}, +{435, 144, 274, 88, 203, 418, 30, 1, 190, 410, 96, 778, 100, 530, 521, 326, 466, 795, 686, 166, 960, 321, 382, 264, 367, 822, 131, 31, 692, 9, 213, 93}, +{76, 72, 90, 21, 37, 179, 12, 205, 32, 428, 148, 38, 308, 405, 4, 413, 57, 184, 749, 245, 316, 221, 54, 645, 288, 1, 152, 155, 464, 257, 2, 14}, +{77, 33, 64, 102, 13, 141, 23, 2, 40, 1, 51, 10, 0, 115, 6, 180, 202, 128, 4, 3, 177, 269, 15, 7, 22, 165, 291, 14, 217, 318, 137, 11}, +{397, 81, 4, 32, 65, 788, 693, 804, 681, 11, 249, 21, 91, 64, 690, 494, 3, 0, 422, 56, 348, 725, 194, 123, 23, 59, 523, 319, 61, 510, 95, 90}, +{60, 126, 16, 7, 92, 121, 314, 246, 35, 107, 150, 132, 14, 146, 24, 18, 199, 298, 232, 71, 359, 140, 672, 97, 392, 649, 5, 423, 95, 21, 22, 388}, +{15, 515, 141, 217, 115, 700, 13, 23, 120, 317, 753, 180, 33, 260, 110, 137, 341, 51, 1, 365, 4, 77, 64, 202, 0, 40, 36, 352, 197, 269, 10, 21}, +{111, 134, 117, 474, 23, 13, 961, 12, 569, 431, 37, 15, 51, 115, 515, 700, 277, 99, 753, 38, 197, 405, 457, 4, 72, 94, 629, 45, 11, 89, 54, 148}, +{23, 13, 51, 5, 1, 15, 2, 21, 12, 202, 141, 0, 515, 165, 120, 32, 4, 64, 700, 3, 115, 197, 269, 125, 753, 7, 9, 128, 6, 180, 453, 403}, +{13, 141, 4, 23, 5, 2, 115, 217, 202, 51, 180, 137, 269, 352, 77, 1, 317, 3, 21, 318, 0, 15, 9, 64, 10, 197, 11, 341, 33, 515, 752, 7}, +{165, 125, 197, 13, 391, 21, 23, 558, 48, 380, 97, 120, 298, 33, 14, 426, 66, 115, 32, 386, 900, 180, 6, 98, 357, 237, 326, 509, 51, 278, 221, 457}, +{120, 82, 15, 260, 515, 1, 351, 77, 450, 700, 13, 21, 141, 23, 753, 202, 217, 93, 110, 33, 51, 854, 5, 128, 326, 102, 137, 180, 817, 48, 269, 352}, +{23, 13, 15, 51, 515, 700, 961, 753, 0, 457, 1, 2, 4, 115, 10, 453, 569, 5, 33, 165, 11, 719, 14, 40, 64, 197, 3, 21, 474, 629, 38, 401}, +{264, 166, 39, 30, 9, 100, 435, 254, 93, 921, 190, 363, 1, 625, 411, 382, 897, 656, 203, 478, 404, 812, 438, 110, 473, 88, 18, 691, 156, 141, 274, 272}, +{9, 0, 252, 100, 166, 39, 101, 265, 364, 68, 88, 329, 520, 18, 419, 676, 118, 167, 404, 604, 16, 1, 21, 30, 212, 158, 553, 49, 382, 274, 48, 13}, +{15, 515, 700, 753, 4, 11, 141, 5, 3, 13, 202, 1, 180, 21, 2, 165, 269, 23, 40, 64, 0, 318, 12, 32, 128, 51, 77, 117, 523, 197, 120, 457}, +{24, 1, 2, 69, 35, 16, 67, 18, 14, 50, 0, 46, 68, 9, 38, 7, 133, 71, 83, 149, 28, 108, 189, 218, 65, 114, 238, 29, 75, 54, 5, 96}, +{90, 289, 214, 64, 874, 13, 77, 712, 66, 751, 4, 23, 51, 192, 32, 0, 202, 194, 312, 177, 33, 65, 234, 104, 875, 288, 59, 5, 835, 416, 102, 95}, +{0, 9, 49, 127, 98, 31, 301, 28, 371, 159, 1, 395, 512, 737, 158, 761, 916, 623, 16, 44, 242, 39, 170, 18, 293, 105, 24, 272, 101, 22, 23, 385}, +{17, 62, 136, 214, 123, 129, 32, 292, 119, 209, 710, 106, 141, 162, 128, 64, 45, 4, 77, 249, 11, 618, 211, 3, 207, 130, 519, 183, 38, 177, 21, 269}, +{5, 107, 581, 356, 279, 32, 441, 362, 493, 660, 13, 298, 0, 534, 49, 147, 21, 22, 132, 121, 97, 423, 7, 590, 259, 683, 14, 786, 126, 508, 60, 246}, +{51, 13, 15, 730, 453, 23, 515, 719, 386, 457, 12, 700, 403, 475, 899, 1, 6, 523, 753, 421, 99, 401, 165, 33, 2, 19, 361, 5, 0, 670, 120, 27}, +{49, 28, 9, 159, 272, 22, 254, 131, 158, 327, 95, 105, 0, 39, 35, 168, 347, 286, 374, 55, 65, 627, 424, 912, 68, 578, 1, 24, 239, 175, 688, 169}, +{15, 515, 700, 33, 753, 4, 77, 141, 341, 317, 1, 10, 13, 180, 102, 22, 40, 117, 115, 365, 5, 901, 23, 197, 134, 11, 217, 351, 64, 82, 21, 137}, +{134, 15, 13, 515, 23, 700, 12, 753, 51, 474, 37, 961, 197, 10, 457, 569, 4, 0, 99, 2, 115, 38, 165, 153, 94, 3, 139, 11, 1, 82, 33, 5}, +{7, 2, 20, 58, 5, 14, 128, 66, 6, 29, 32, 43, 21, 52, 16, 38, 631, 61, 74, 97, 46, 135, 113, 25, 202, 192, 13, 0, 884, 45, 112, 87}, +{77, 13, 33, 202, 23, 128, 102, 4, 141, 342, 117, 0, 269, 318, 134, 22, 11, 21, 32, 153, 403, 291, 49, 64, 137, 51, 40, 15, 494, 5, 196, 98}, +{2, 1, 14, 6, 46, 38, 29, 65, 5, 36, 67, 0, 103, 7, 22, 86, 133, 50, 108, 208, 52, 83, 24, 323, 283, 69, 28, 18, 10, 25, 23, 75}, +{15, 515, 700, 753, 1, 5, 4, 2, 3, 13, 0, 11, 180, 341, 12, 33, 10, 197, 134, 365, 77, 23, 21, 901, 6, 117, 165, 7, 37, 32, 17, 102}, +{203, 268, 206, 93, 417, 940, 31, 8, 120, 137, 44, 499, 959, 473, 202, 692, 728, 559, 0, 260, 10, 326, 141, 564, 817, 127, 341, 1, 450, 22, 110, 23}, +{15, 82, 515, 120, 700, 0, 10, 753, 33, 8, 64, 165, 110, 31, 260, 93, 13, 197, 23, 22, 40, 4, 351, 44, 77, 9, 11, 153, 102, 51, 1, 196}, +{60, 0, 16, 7, 14, 43, 20, 71, 28, 10, 2, 22, 154, 18, 13, 24, 92, 1, 51, 576, 35, 615, 805, 925, 68, 126, 124, 149, 97, 64, 23, 55}, +{19, 6, 26, 80, 5, 84, 27, 17, 25, 2, 504, 129, 45, 240, 56, 123, 4, 119, 618, 1, 76, 106, 64, 51, 14, 3, 128, 65, 32, 710, 0, 42}, +{15, 515, 700, 753, 13, 4, 77, 23, 33, 51, 0, 5, 8, 10, 11, 31, 44, 1, 82, 22, 202, 64, 110, 102, 93, 21, 291, 40, 141, 180, 9, 49}, +{195, 98, 271, 223, 132, 167, 146, 407, 1, 360, 121, 834, 393, 591, 212, 199, 293, 259, 522, 107, 354, 147, 156, 191, 807, 590, 48, 18, 125, 16, 765, 541}, +{128, 202, 77, 210, 402, 318, 33, 102, 6, 40, 403, 29, 342, 269, 196, 757, 99, 139, 2, 111, 42, 4, 494, 117, 275, 300, 13, 12, 678, 0, 177, 122}, +{13, 33, 23, 40, 51, 102, 4, 117, 77, 64, 134, 0, 128, 153, 202, 196, 453, 11, 15, 12, 1, 22, 403, 141, 59, 14, 10, 475, 515, 65, 700, 95}, +{7, 16, 14, 24, 18, 2, 28, 0, 92, 71, 1, 22, 6, 35, 60, 20, 168, 10, 154, 118, 5, 302, 124, 69, 97, 109, 703, 158, 420, 12, 149, 66}, +{15, 1, 515, 23, 0, 13, 700, 2, 51, 753, 180, 5, 120, 165, 197, 21, 115, 4, 33, 9, 141, 7, 12, 6, 3, 457, 386, 202, 260, 523, 8, 31}, +{60, 107, 121, 132, 146, 126, 199, 279, 150, 92, 16, 649, 441, 35, 955, 7, 21, 0, 423, 5, 18, 195, 598, 298, 493, 356, 32, 653, 22, 362, 953, 10}, +{31, 44, 98, 276, 284, 299, 116, 935, 9, 201, 0, 131, 39, 127, 144, 662, 1, 137, 371, 492, 567, 489, 93, 254, 49, 268, 22, 28, 30, 293, 434, 737}, +{13, 15, 23, 515, 700, 0, 1, 51, 753, 4, 2, 10, 77, 202, 5, 115, 3, 165, 197, 457, 9, 12, 11, 961, 33, 120, 22, 141, 180, 7, 6, 40}, +{123, 162, 184, 257, 17, 183, 229, 130, 129, 3, 84, 136, 99, 152, 556, 383, 57, 497, 12, 205, 4, 62, 56, 452, 80, 266, 128, 14, 40, 119, 27, 106}, +{196, 33, 117, 40, 153, 23, 134, 13, 51, 102, 453, 0, 15, 475, 12, 14, 515, 2, 22, 700, 4, 21, 753, 64, 401, 670, 730, 1, 9, 11, 10, 99}, +{224, 219, 187, 131, 258, 385, 442, 871, 836, 31, 98, 908, 44, 574, 127, 944, 137, 839, 116, 36, 613, 1, 254, 39, 926, 160, 829, 96, 93, 371, 860, 827}, +{121, 195, 156, 132, 146, 360, 590, 407, 786, 522, 883, 591, 259, 929, 626, 941, 150, 687, 5, 55, 296, 379, 467, 178, 586, 465, 279, 21, 1, 13, 60, 354}, +{2, 1, 14, 29, 6, 5, 46, 52, 38, 19, 114, 75, 26, 65, 108, 96, 25, 50, 36, 70, 103, 309, 17, 236, 218, 74, 12, 86, 0, 3, 10, 112}, +{15, 515, 82, 700, 120, 753, 10, 0, 8, 197, 260, 165, 351, 64, 13, 110, 117, 93, 31, 1, 9, 33, 22, 23, 457, 44, 450, 77, 102, 898, 40, 49}, +{7, 66, 97, 2, 172, 74, 226, 52, 29, 135, 192, 232, 43, 324, 92, 5, 38, 20, 222, 14, 6, 568, 87, 107, 353, 620, 580, 16, 138, 174, 448, 32}, +{62, 129, 123, 162, 136, 249, 618, 183, 507, 57, 4, 152, 17, 59, 11, 184, 117, 77, 3, 128, 211, 41, 130, 205, 12, 40, 33, 106, 64, 229, 38, 313}, +{1, 13, 15, 2, 4, 515, 23, 0, 3, 115, 700, 5, 51, 77, 341, 141, 753, 180, 33, 217, 197, 202, 901, 6, 21, 165, 11, 365, 318, 317, 10, 102}, +{6, 26, 235, 19, 145, 47, 112, 78, 64, 27, 453, 95, 29, 444, 25, 624, 85, 108, 648, 70, 32, 130, 74, 42, 711, 630, 632, 138, 65, 122, 113, 730}, +{23, 51, 12, 15, 13, 99, 515, 153, 117, 10, 700, 37, 120, 82, 165, 2, 753, 64, 128, 0, 403, 3, 5, 1, 134, 197, 453, 31, 202, 457, 110, 21}, +{16, 24, 18, 71, 64, 35, 92, 7, 246, 146, 9, 108, 60, 118, 199, 5, 140, 2, 267, 0, 230, 830, 32, 133, 1, 68, 50, 330, 247, 563, 36, 12}, +{15, 515, 700, 753, 0, 1, 13, 2, 23, 3, 4, 217, 51, 5, 115, 8, 9, 180, 341, 10, 7, 6, 317, 77, 33, 372, 901, 197, 365, 11, 120, 165}, +{234, 639, 178, 202, 77, 142, 5, 455, 450, 49, 416, 0, 147, 427, 198, 21, 315, 329, 13, 318, 325, 557, 120, 344, 113, 259, 22, 128, 61, 105, 23, 494}, +{1, 31, 36, 44, 141, 180, 55, 2, 64, 22, 98, 116, 13, 352, 0, 115, 10, 127, 5, 164, 253, 498, 237, 165, 341, 197, 4, 86, 15, 170, 125, 23}, +{15, 120, 13, 141, 23, 260, 217, 515, 1, 77, 51, 110, 180, 700, 317, 82, 269, 137, 115, 202, 21, 753, 64, 5, 351, 291, 0, 450, 352, 93, 36, 326}, +{26, 6, 112, 396, 19, 145, 25, 122, 648, 287, 42, 74, 624, 222, 416, 45, 138, 66, 644, 151, 113, 651, 29, 573, 64, 280, 445, 27, 525, 85, 70, 58}, +{156, 360, 5, 146, 121, 21, 271, 522, 354, 132, 49, 13, 18, 195, 16, 340, 60, 591, 446, 586, 727, 0, 107, 407, 167, 48, 1, 463, 199, 566, 32, 23}, +{5, 61, 49, 147, 178, 612, 660, 120, 21, 182, 23, 427, 259, 683, 33, 4, 77, 70, 13, 3, 376, 98, 64, 0, 481, 344, 48, 595, 291, 263, 141, 51}, +{89, 79, 468, 179, 358, 205, 94, 405, 115, 498, 72, 180, 365, 431, 37, 111, 341, 734, 188, 317, 482, 217, 11, 4, 245, 152, 413, 216, 12, 474, 490, 752}, +{24, 16, 35, 68, 18, 71, 7, 92, 0, 108, 9, 14, 118, 101, 336, 175, 375, 302, 28, 124, 154, 55, 149, 60, 398, 1, 65, 2, 140, 273, 345, 230}, +{51, 730, 421, 801, 453, 386, 23, 523, 13, 475, 719, 401, 670, 365, 899, 403, 115, 457, 758, 165, 33, 494, 450, 6, 423, 805, 629, 56, 569, 514, 958, 388}, +{113, 45, 6, 311, 29, 2, 151, 614, 145, 491, 112, 80, 5, 27, 61, 74, 315, 66, 209, 631, 19, 25, 58, 17, 73, 26, 1, 243, 70, 64, 611, 287}, +{4, 339, 188, 471, 11, 59, 79, 12, 377, 94, 99, 33, 77, 102, 51, 111, 37, 152, 13, 961, 474, 542, 40, 342, 3, 23, 128, 403, 202, 177, 184, 57}, +{15, 4, 515, 11, 700, 33, 82, 40, 0, 120, 753, 10, 8, 110, 13, 93, 23, 165, 77, 260, 64, 31, 22, 51, 44, 102, 351, 1, 125, 9, 197, 21}, +{16, 24, 18, 0, 35, 68, 28, 71, 124, 118, 60, 7, 9, 55, 14, 92, 109, 101, 419, 175, 22, 252, 154, 375, 149, 302, 158, 346, 2, 49, 1, 126}, +{17, 45, 227, 21, 106, 3, 2, 243, 209, 5, 48, 32, 221, 62, 207, 50, 29, 186, 290, 270, 263, 52, 14, 496, 400, 119, 46, 255, 54, 430, 38, 721}, +{340, 354, 586, 658, 156, 195, 698, 668, 1, 296, 9, 18, 883, 363, 447, 379, 303, 98, 411, 13, 31, 163, 51, 5, 371, 48, 919, 846, 121, 21, 360, 70}, +{277, 153, 111, 12, 23, 51, 474, 99, 38, 37, 139, 117, 41, 457, 79, 453, 542, 13, 11, 33, 134, 157, 629, 188, 961, 14, 196, 401, 102, 569, 15, 94}, +{0, 18, 16, 159, 49, 24, 9, 105, 35, 68, 7, 28, 22, 1, 60, 344, 55, 101, 109, 2, 14, 158, 13, 23, 71, 118, 455, 286, 272, 424, 5, 327}, +{0, 105, 9, 49, 16, 18, 158, 28, 518, 24, 101, 320, 1, 68, 170, 301, 272, 127, 7, 286, 35, 890, 109, 39, 159, 98, 21, 344, 31, 55, 371, 23}, +{141, 1, 180, 15, 13, 2, 365, 217, 515, 352, 317, 115, 341, 0, 4, 5, 269, 700, 23, 21, 3, 752, 197, 77, 753, 51, 31, 901, 10, 202, 8, 64}, +{4, 23, 51, 33, 19, 17, 102, 153, 485, 880, 40, 403, 196, 26, 300, 453, 27, 117, 78, 0, 12, 200, 47, 5, 11, 14, 342, 99, 53, 77, 475, 2}, +{62, 184, 56, 440, 130, 229, 183, 3, 556, 152, 99, 162, 12, 266, 17, 548, 136, 57, 305, 161, 123, 14, 452, 4, 383, 403, 257, 34, 40, 84, 33, 139}, +{13, 23, 77, 141, 64, 202, 33, 51, 269, 115, 0, 102, 21, 4, 217, 128, 5, 32, 318, 137, 291, 9, 15, 2, 180, 10, 3, 317, 177, 515, 7, 6}, +{1, 22, 36, 105, 170, 0, 86, 2, 31, 28, 239, 64, 55, 5, 10, 98, 9, 44, 127, 95, 654, 67, 301, 143, 13, 12, 49, 23, 320, 141, 83, 21}, +{15, 515, 700, 753, 0, 1, 13, 2, 23, 901, 5, 8, 51, 82, 9, 180, 457, 4, 7, 12, 3, 6, 10, 120, 341, 141, 22, 898, 197, 351, 115, 260}, +{1, 39, 274, 98, 100, 265, 190, 30, 438, 310, 166, 223, 88, 96, 909, 31, 264, 625, 530, 9, 382, 812, 21, 252, 593, 0, 254, 539, 44, 131, 23, 778}, +{18, 212, 167, 118, 363, 1, 447, 411, 146, 60, 271, 16, 781, 121, 647, 9, 621, 562, 21, 478, 664, 68, 815, 5, 354, 98, 48, 101, 24, 446, 777, 463}, +{24, 28, 22, 0, 7, 1, 2, 16, 14, 65, 35, 49, 158, 95, 109, 159, 55, 105, 10, 18, 124, 9, 67, 5, 239, 149, 12, 289, 108, 68, 21, 424}, +{105, 22, 131, 272, 286, 98, 55, 239, 1, 31, 320, 9, 127, 327, 36, 185, 28, 374, 86, 219, 0, 64, 187, 44, 578, 164, 224, 913, 535, 115, 601, 13}, +{22, 31, 28, 301, 127, 98, 44, 0, 105, 1, 512, 395, 9, 293, 109, 299, 95, 338, 239, 125, 242, 116, 36, 320, 55, 841, 900, 685, 599, 23, 13, 763}, +{2, 1, 58, 29, 5, 14, 52, 46, 186, 334, 45, 155, 151, 50, 400, 75, 38, 69, 502, 61, 48, 227, 223, 7, 163, 17, 262, 67, 549, 21, 70, 113}, +{7, 107, 135, 232, 97, 14, 2, 92, 66, 16, 172, 192, 278, 387, 298, 356, 38, 35, 448, 52, 46, 43, 60, 29, 20, 126, 324, 526, 357, 359, 64, 5}, +{20, 43, 104, 426, 173, 7, 560, 414, 707, 784, 319, 81, 0, 861, 422, 819, 38, 74, 715, 52, 376, 97, 879, 32, 330, 22, 49, 64, 66, 95, 192, 526}, +{104, 74, 636, 66, 204, 0, 355, 81, 222, 25, 29, 319, 145, 784, 20, 65, 90, 4, 174, 194, 7, 64, 6, 746, 138, 173, 750, 715, 91, 43, 192, 32}, +{0, 9, 101, 35, 68, 39, 65, 28, 252, 124, 67, 154, 364, 336, 100, 166, 30, 1, 289, 55, 149, 346, 16, 114, 158, 88, 439, 24, 429, 22, 570, 194}, +{57, 14, 4, 231, 236, 585, 176, 59, 369, 23, 361, 13, 719, 51, 300, 342, 12, 457, 56, 3, 62, 38, 202, 401, 34, 46, 2, 322, 11, 215, 210, 507}, +{1, 2, 15, 3, 141, 0, 515, 5, 33, 700, 13, 64, 77, 180, 6, 128, 753, 10, 4, 269, 102, 202, 11, 7, 134, 197, 352, 120, 117, 318, 12, 291}, +{5, 1, 21, 202, 13, 32, 48, 23, 0, 61, 259, 22, 494, 120, 70, 49, 51, 18, 137, 128, 465, 12, 178, 115, 2, 453, 403, 141, 58, 3, 90, 450}, +{141, 205, 4, 72, 59, 79, 245, 11, 352, 94, 152, 76, 247, 216, 21, 188, 452, 217, 497, 12, 89, 37, 111, 339, 588, 77, 64, 875, 864, 115, 358, 464}, +{15, 515, 700, 753, 0, 1, 2, 13, 5, 4, 23, 3, 8, 341, 365, 51, 115, 10, 120, 457, 6, 141, 77, 197, 31, 7, 165, 9, 202, 450, 961, 260}, +{5, 2, 50, 14, 58, 38, 171, 46, 29, 1, 45, 186, 17, 52, 155, 218, 48, 281, 61, 487, 54, 36, 67, 21, 328, 334, 151, 227, 760, 114, 400, 133}, +{457, 120, 70, 125, 318, 64, 23, 48, 795, 291, 202, 761, 751, 415, 77, 846, 269, 758, 21, 237, 96, 260, 391, 165, 87, 1, 128, 5, 221, 13, 137, 763}, +{13, 23, 51, 33, 4, 40, 117, 102, 453, 64, 153, 196, 0, 77, 15, 11, 12, 475, 1, 65, 134, 10, 515, 22, 21, 14, 700, 59, 403, 141, 2, 753}, +{229, 152, 57, 266, 452, 381, 432, 12, 313, 184, 99, 471, 17, 4, 62, 339, 157, 3, 129, 59, 128, 11, 369, 37, 77, 38, 40, 123, 5, 497, 188, 257}, +{49, 28, 109, 22, 159, 9, 272, 95, 105, 131, 55, 35, 254, 168, 39, 327, 169, 0, 1, 286, 175, 374, 347, 158, 420, 67, 36, 194, 312, 424, 627, 346}, +{5, 2, 61, 29, 45, 58, 80, 311, 1, 17, 209, 227, 52, 243, 106, 869, 454, 151, 592, 496, 48, 334, 14, 155, 6, 186, 46, 171, 75, 21, 255, 667}, +{244, 44, 110, 141, 260, 30, 269, 352, 839, 131, 574, 228, 373, 276, 1, 406, 219, 717, 217, 137, 253, 224, 120, 93, 36, 31, 567, 116, 661, 187, 341, 88}, +{12, 99, 79, 139, 11, 453, 196, 51, 277, 474, 111, 23, 542, 37, 94, 188, 33, 13, 401, 775, 40, 961, 313, 102, 4, 339, 153, 485, 629, 134, 300, 431}, +{16, 35, 9, 0, 68, 24, 149, 69, 67, 18, 1, 114, 65, 230, 71, 7, 103, 133, 50, 167, 212, 118, 101, 191, 140, 64, 399, 28, 124, 283, 55, 565}, +{88, 30, 274, 435, 131, 613, 190, 100, 93, 829, 166, 1, 187, 795, 530, 127, 382, 957, 960, 160, 31, 137, 466, 264, 39, 800, 406, 254, 28, 473, 521, 219}, +{167, 16, 18, 118, 212, 24, 60, 71, 101, 68, 191, 9, 375, 411, 363, 35, 0, 1, 589, 199, 302, 21, 447, 55, 146, 126, 92, 271, 647, 121, 562, 48}, +{64, 141, 86, 177, 77, 128, 147, 597, 304, 95, 269, 102, 275, 4, 352, 49, 120, 5, 372, 194, 465, 13, 588, 237, 947, 216, 202, 180, 612, 751, 107, 534}, +{18, 65, 90, 403, 523, 289, 240, 214, 194, 102, 701, 475, 202, 217, 283, 862, 389, 51, 33, 0, 494, 421, 453, 817, 84, 64, 847, 899, 352, 13, 23, 437}, +{13, 51, 23, 202, 5, 12, 21, 128, 15, 115, 0, 1, 141, 120, 64, 32, 4, 2, 515, 403, 165, 457, 3, 10, 700, 99, 453, 318, 719, 450, 308, 401}, +{98, 223, 393, 31, 1, 271, 834, 791, 167, 44, 202, 64, 93, 697, 5, 116, 77, 125, 450, 446, 212, 18, 541, 293, 51, 120, 195, 132, 284, 13, 807, 765}, +{15, 515, 700, 753, 4, 11, 23, 13, 40, 51, 82, 165, 0, 110, 93, 33, 141, 64, 120, 5, 10, 77, 3, 102, 180, 32, 202, 125, 8, 197, 31, 21}, +{15, 515, 700, 753, 0, 1, 13, 2, 901, 23, 5, 341, 3, 51, 82, 8, 4, 180, 961, 9, 115, 10, 12, 6, 898, 7, 351, 141, 134, 22, 31, 120}, +{234, 416, 77, 5, 315, 639, 325, 202, 147, 198, 113, 49, 450, 61, 455, 142, 0, 21, 22, 342, 329, 494, 178, 58, 102, 427, 318, 230, 13, 120, 43, 470}, +{60, 146, 16, 18, 156, 126, 121, 271, 199, 360, 132, 24, 167, 0, 640, 10, 71, 522, 21, 92, 5, 340, 107, 354, 118, 150, 22, 195, 446, 35, 28, 212}, +{4, 361, 11, 14, 56, 368, 377, 161, 27, 12, 300, 77, 59, 200, 17, 554, 202, 33, 40, 494, 495, 21, 210, 80, 757, 25, 128, 23, 19, 38, 444, 53}, +{141, 82, 217, 351, 15, 352, 120, 1, 180, 260, 515, 64, 854, 36, 700, 317, 752, 372, 13, 269, 77, 753, 922, 21, 349, 23, 202, 110, 93, 137, 51, 373}, +{15, 515, 700, 753, 77, 13, 0, 1, 23, 33, 102, 2, 51, 4, 3, 5, 291, 217, 10, 9, 450, 120, 341, 7, 317, 6, 11, 117, 115, 8, 260, 180}, +{15, 515, 120, 13, 700, 23, 77, 141, 1, 260, 0, 753, 180, 51, 137, 202, 115, 365, 110, 291, 217, 5, 128, 9, 21, 341, 197, 269, 2, 450, 317, 165}, +{174, 6, 348, 85, 138, 74, 280, 204, 66, 233, 192, 355, 289, 65, 81, 580, 636, 353, 25, 91, 104, 343, 673, 214, 64, 95, 42, 712, 792, 32, 194, 90}, +{152, 497, 452, 59, 4, 216, 11, 79, 94, 77, 128, 188, 269, 339, 588, 33, 76, 529, 318, 32, 141, 471, 12, 202, 111, 21, 5, 51, 37, 90, 72, 177}, +{417, 499, 10, 141, 253, 244, 110, 559, 8, 564, 180, 260, 728, 120, 352, 638, 642, 341, 951, 206, 143, 752, 901, 93, 137, 661, 922, 373, 44, 31, 811, 197}, +{13, 77, 23, 33, 4, 51, 0, 102, 128, 59, 141, 40, 64, 115, 177, 10, 137, 22, 202, 2, 7, 11, 90, 1, 117, 180, 269, 14, 49, 6, 134, 3}, +{1, 2, 22, 0, 36, 5, 67, 50, 14, 28, 12, 86, 38, 46, 83, 168, 194, 65, 103, 114, 49, 7, 10, 95, 21, 69, 23, 24, 128, 51, 55, 13}, +{17, 106, 119, 207, 255, 306, 742, 378, 84, 62, 136, 45, 3, 5, 240, 80, 61, 56, 209, 383, 311, 790, 655, 32, 2, 440, 76, 151, 58, 29, 179, 263}, +{3, 128, 1, 141, 2, 202, 33, 5, 64, 15, 0, 515, 102, 13, 269, 10, 700, 180, 134, 51, 120, 6, 77, 318, 23, 137, 17, 117, 753, 197, 82, 153}, +{514, 38, 377, 328, 11, 57, 41, 248, 880, 266, 556, 4, 152, 361, 471, 757, 485, 403, 305, 102, 3, 211, 313, 99, 457, 130, 12, 14, 157, 40, 23, 54}, +{68, 0, 167, 101, 9, 118, 264, 520, 16, 18, 21, 478, 562, 1, 124, 212, 100, 936, 664, 777, 191, 88, 806, 154, 48, 24, 759, 604, 35, 252, 265, 65}, +{230, 689, 699, 213, 466, 352, 217, 831, 30, 443, 418, 144, 854, 201, 840, 855, 1, 251, 203, 317, 530, 957, 96, 93, 822, 539, 36, 752, 351, 137, 83, 800}, +{33, 77, 102, 117, 15, 82, 13, 134, 23, 64, 0, 515, 120, 153, 51, 4, 40, 128, 700, 260, 202, 141, 196, 22, 753, 11, 351, 10, 1, 326, 95, 269}, +{11, 40, 33, 51, 117, 13, 542, 328, 14, 134, 38, 153, 23, 12, 485, 231, 102, 54, 775, 37, 3, 377, 111, 139, 211, 4, 457, 403, 369, 475, 99, 719}, +{33, 64, 77, 128, 141, 2, 1, 202, 102, 13, 23, 117, 0, 15, 3, 153, 51, 134, 10, 40, 6, 5, 515, 269, 137, 180, 318, 165, 700, 7, 196, 753}, +{15, 515, 700, 753, 4, 1, 5, 11, 13, 21, 33, 180, 93, 141, 64, 2, 23, 77, 82, 3, 0, 102, 32, 40, 352, 341, 10, 197, 98, 110, 117, 901}, +{1, 2, 14, 67, 50, 46, 38, 24, 103, 83, 0, 5, 36, 28, 29, 133, 114, 96, 65, 52, 18, 75, 54, 108, 22, 7, 238, 58, 160, 9, 361, 69}, +{258, 201, 276, 137, 160, 860, 116, 261, 295, 843, 567, 144, 131, 44, 187, 268, 943, 219, 284, 31, 202, 935, 141, 98, 662, 203, 127, 96, 36, 93, 224, 1}, +{7, 2, 14, 16, 46, 87, 75, 52, 92, 278, 29, 38, 140, 70, 1, 5, 35, 294, 24, 262, 135, 69, 171, 172, 58, 409, 112, 60, 50, 66, 97, 12}, +{13, 23, 0, 2, 51, 1, 33, 4, 115, 10, 15, 141, 77, 3, 5, 180, 217, 515, 9, 7, 64, 11, 700, 6, 102, 40, 197, 22, 317, 753, 165, 202}, +{74, 145, 6, 66, 25, 204, 42, 29, 222, 337, 138, 26, 7, 525, 192, 174, 746, 287, 544, 135, 415, 2, 609, 632, 112, 64, 87, 0, 85, 45, 712, 396}, +{77, 33, 102, 15, 217, 13, 23, 141, 202, 515, 51, 700, 291, 4, 269, 753, 317, 180, 21, 64, 318, 115, 128, 0, 275, 2, 352, 196, 3, 5, 137, 11}, +{187, 219, 258, 871, 44, 442, 160, 574, 137, 224, 908, 116, 839, 131, 36, 926, 276, 201, 93, 228, 202, 860, 31, 613, 144, 531, 406, 1, 902, 30, 190, 318}, +{1, 372, 141, 5, 21, 77, 225, 744, 96, 30, 23, 349, 13, 291, 269, 284, 69, 442, 459, 144, 303, 839, 217, 622, 160, 330, 260, 48, 120, 410, 189, 352}, +{66, 222, 2, 74, 29, 87, 135, 6, 7, 145, 52, 25, 294, 337, 226, 172, 138, 331, 42, 70, 97, 112, 26, 1, 632, 192, 43, 5, 415, 609, 461, 353}, +{45, 17, 106, 209, 5, 2, 21, 29, 48, 207, 3, 186, 243, 155, 255, 263, 454, 119, 400, 496, 270, 14, 290, 62, 425, 1, 171, 32, 659, 52, 38, 56}, +{93, 88, 141, 120, 30, 213, 260, 373, 100, 717, 459, 82, 110, 1, 166, 450, 180, 321, 217, 372, 36, 269, 131, 225, 22, 352, 326, 466, 473, 187, 244, 410}, +{266, 57, 152, 381, 313, 471, 12, 229, 99, 369, 339, 62, 157, 3, 4, 37, 77, 38, 188, 17, 11, 162, 40, 184, 129, 59, 475, 775, 128, 452, 403, 453}, +{217, 352, 317, 141, 752, 15, 180, 515, 372, 365, 700, 341, 753, 349, 77, 21, 291, 1, 115, 244, 64, 120, 13, 98, 269, 82, 5, 498, 864, 351, 23, 144}, +{14, 514, 369, 102, 403, 377, 51, 719, 880, 153, 23, 13, 457, 11, 485, 4, 401, 12, 328, 453, 33, 40, 117, 57, 629, 38, 730, 236, 134, 670, 361, 961}, +{107, 7, 172, 14, 92, 135, 2, 359, 60, 314, 46, 16, 126, 278, 232, 150, 279, 32, 38, 392, 298, 5, 35, 97, 24, 192, 259, 288, 330, 52, 356, 312}, +{0, 4, 25, 13, 59, 90, 65, 23, 26, 19, 18, 12, 5, 216, 91, 51, 389, 33, 77, 11, 22, 85, 27, 81, 21, 177, 746, 45, 42, 194, 37, 123}, +{5, 49, 315, 202, 416, 77, 455, 639, 450, 21, 197, 137, 350, 13, 408, 0, 329, 318, 494, 344, 61, 402, 64, 509, 347, 120, 113, 48, 95, 713, 308, 401}, +{130, 47, 381, 390, 59, 90, 200, 214, 289, 6, 65, 472, 29, 64, 874, 648, 50, 751, 624, 26, 52, 32, 4, 194, 875, 714, 85, 249, 247, 33, 881, 19}, +{51, 23, 453, 13, 719, 12, 457, 165, 37, 730, 99, 4, 386, 197, 401, 17, 11, 2, 3, 15, 5, 961, 475, 6, 515, 64, 54, 700, 32, 115, 0, 403}, +{15, 515, 1, 13, 700, 2, 23, 0, 753, 5, 3, 180, 51, 4, 165, 12, 141, 21, 197, 457, 7, 115, 6, 9, 352, 10, 120, 202, 8, 341, 11, 77}, +{0, 9, 1, 67, 35, 28, 68, 16, 24, 65, 18, 69, 50, 114, 103, 12, 22, 13, 5, 101, 2, 96, 23, 83, 149, 21, 39, 55, 7, 175, 433, 124}, +{28, 105, 22, 0, 1, 320, 170, 9, 49, 301, 109, 95, 127, 31, 98, 55, 65, 35, 2, 24, 168, 159, 36, 713, 16, 740, 13, 338, 21, 44, 512, 23}, +{13, 77, 4, 51, 23, 33, 102, 202, 128, 59, 40, 0, 64, 141, 117, 403, 115, 11, 15, 318, 153, 269, 22, 515, 475, 134, 10, 494, 177, 1, 90, 210}, +{13, 23, 0, 51, 77, 33, 2, 141, 4, 10, 1, 64, 115, 102, 3, 6, 22, 15, 217, 11, 180, 7, 40, 515, 165, 202, 177, 9, 269, 128, 700, 5}, +{456, 116, 492, 8, 949, 268, 867, 391, 203, 51, 499, 13, 719, 386, 31, 791, 457, 918, 125, 10, 23, 93, 479, 685, 417, 0, 22, 338, 506, 551, 870, 730}, +{17, 237, 45, 180, 106, 62, 32, 64, 115, 41, 136, 498, 255, 21, 197, 129, 241, 13, 3, 227, 23, 352, 165, 752, 350, 365, 449, 155, 4, 546, 476, 38}, +{1, 15, 180, 515, 0, 2, 341, 700, 901, 352, 4, 141, 13, 3, 752, 5, 753, 217, 317, 115, 365, 23, 197, 21, 51, 165, 31, 6, 269, 202, 77, 7}, +{205, 141, 216, 269, 497, 4, 588, 76, 59, 152, 128, 452, 79, 77, 875, 11, 72, 94, 188, 217, 352, 12, 247, 37, 90, 64, 32, 1, 474, 23, 947, 372}, +{64, 247, 217, 237, 317, 180, 752, 115, 349, 141, 498, 13, 437, 304, 23, 372, 352, 164, 579, 291, 33, 864, 177, 197, 0, 490, 72, 10, 482, 77, 269, 51}, +{2, 1, 0, 13, 15, 141, 3, 77, 5, 515, 64, 33, 23, 180, 6, 700, 4, 117, 217, 7, 10, 11, 102, 165, 753, 197, 115, 134, 40, 352, 12, 269}, +{11, 40, 38, 328, 33, 542, 12, 313, 41, 339, 23, 157, 377, 117, 369, 51, 471, 99, 775, 485, 13, 305, 457, 57, 14, 475, 37, 248, 4, 54, 188, 719}, +{33, 77, 102, 40, 13, 23, 0, 51, 4, 128, 64, 202, 117, 141, 22, 196, 153, 10, 134, 15, 59, 269, 1, 137, 65, 11, 403, 318, 453, 86, 515, 177}, +{472, 80, 34, 250, 495, 161, 17, 14, 469, 176, 128, 4, 389, 106, 283, 436, 216, 527, 3, 297, 483, 177, 53, 56, 231, 194, 119, 84, 719, 57, 255, 59}, +{317, 352, 180, 141, 217, 752, 115, 341, 365, 244, 1, 269, 202, 901, 253, 15, 21, 498, 372, 4, 137, 515, 13, 2, 700, 318, 5, 197, 23, 143, 753, 349}, +{9, 39, 101, 18, 265, 100, 333, 520, 252, 16, 0, 329, 593, 1, 553, 364, 68, 167, 310, 30, 121, 254, 118, 158, 363, 166, 60, 604, 272, 24, 286, 404}, +{15, 515, 1, 180, 700, 901, 0, 2, 753, 341, 752, 4, 3, 13, 115, 365, 317, 5, 23, 197, 141, 217, 165, 352, 6, 22, 36, 9, 137, 51, 7, 10}, +{131, 39, 9, 829, 166, 613, 578, 827, 1, 30, 716, 254, 100, 98, 31, 224, 0, 406, 228, 310, 616, 219, 44, 846, 127, 190, 938, 96, 265, 371, 856, 438}, +{17, 64, 62, 106, 141, 751, 136, 292, 32, 129, 352, 41, 38, 476, 86, 128, 214, 237, 5, 177, 123, 209, 217, 45, 269, 954, 162, 710, 180, 3, 90, 4}, +{25, 42, 235, 65, 650, 736, 605, 6, 630, 85, 123, 343, 233, 256, 26, 122, 63, 389, 141, 249, 416, 444, 368, 194, 19, 108, 138, 174, 90, 0, 544, 511}, +{184, 229, 152, 57, 266, 432, 497, 452, 17, 381, 619, 257, 313, 12, 4, 205, 59, 3, 99, 471, 157, 128, 5, 129, 339, 369, 77, 11, 32, 45, 202, 2}, +{137, 202, 160, 860, 141, 30, 93, 567, 36, 276, 295, 261, 131, 39, 9, 964, 201, 843, 1, 98, 800, 318, 116, 22, 943, 187, 10, 219, 206, 44, 269, 535}, +{0, 493, 125, 64, 49, 9, 279, 10, 35, 18, 93, 55, 293, 31, 14, 13, 194, 165, 325, 48, 22, 132, 21, 107, 98, 389, 44, 581, 342, 259, 174, 137}, +{15, 515, 700, 753, 4, 33, 13, 77, 23, 5, 51, 32, 102, 40, 93, 11, 349, 141, 21, 8, 82, 202, 64, 31, 110, 10, 117, 0, 1, 44, 3, 318}, +{110, 253, 854, 811, 352, 141, 244, 951, 180, 642, 661, 384, 498, 143, 752, 317, 911, 10, 269, 206, 559, 351, 261, 120, 902, 533, 922, 959, 365, 160, 332, 217}, +{2, 29, 70, 1, 75, 52, 6, 220, 26, 112, 145, 331, 74, 163, 19, 69, 38, 324, 46, 58, 14, 5, 25, 21, 278, 223, 50, 307, 66, 7, 67, 409}, +{13, 23, 77, 33, 51, 4, 64, 141, 115, 102, 0, 2, 128, 177, 40, 11, 202, 10, 6, 180, 7, 15, 269, 1, 32, 217, 59, 22, 291, 3, 137, 515}, +{340, 897, 691, 478, 658, 264, 914, 382, 100, 812, 363, 1, 724, 156, 166, 698, 88, 521, 39, 404, 682, 447, 296, 96, 303, 411, 30, 909, 9, 274, 656, 772}, +{9, 18, 310, 101, 265, 159, 326, 120, 105, 158, 33, 363, 77, 195, 51, 55, 13, 39, 354, 132, 23, 7, 28, 639, 16, 137, 98, 1, 252, 272, 709, 49}, +{57, 313, 471, 12, 99, 369, 157, 339, 266, 152, 38, 37, 475, 453, 328, 775, 11, 40, 59, 188, 77, 514, 401, 403, 342, 4, 139, 33, 377, 51, 229, 14}, +{16, 7, 24, 14, 35, 140, 60, 92, 18, 69, 71, 2, 189, 1, 46, 230, 108, 388, 150, 38, 21, 172, 278, 67, 246, 267, 50, 309, 236, 135, 451, 0}, +{206, 417, 93, 940, 959, 473, 499, 203, 8, 137, 559, 728, 31, 202, 44, 120, 450, 141, 10, 260, 116, 564, 22, 326, 269, 318, 268, 244, 0, 1, 253, 638}, +{15, 515, 700, 753, 1, 0, 13, 2, 23, 4, 3, 51, 5, 217, 7, 77, 341, 115, 8, 9, 10, 33, 6, 180, 317, 349, 291, 120, 11, 165, 457, 901}, +{1, 2, 5, 14, 48, 21, 290, 32, 50, 45, 38, 46, 263, 207, 155, 72, 76, 29, 17, 408, 425, 171, 89, 52, 7, 0, 292, 449, 3, 227, 513, 428}, +{121, 132, 354, 167, 271, 223, 146, 98, 18, 463, 1, 668, 446, 195, 407, 60, 212, 447, 781, 48, 360, 363, 411, 522, 156, 393, 807, 9, 21, 16, 293, 13}, +{131, 578, 105, 371, 219, 224, 716, 616, 187, 49, 9, 254, 737, 159, 385, 98, 258, 127, 272, 761, 0, 916, 623, 910, 28, 286, 39, 31, 22, 518, 924, 242}, +{302, 467, 97, 6, 273, 1, 24, 484, 124, 51, 36, 18, 2, 398, 453, 421, 523, 69, 7, 23, 13, 403, 386, 150, 66, 0, 298, 65, 426, 165, 22, 158}, +{30, 190, 530, 88, 1, 100, 778, 539, 625, 274, 382, 410, 96, 731, 960, 39, 795, 321, 9, 131, 264, 144, 840, 748, 44, 166, 669, 957, 36, 31, 435, 228}, +{141, 1, 2, 128, 64, 33, 15, 202, 3, 0, 180, 5, 13, 77, 515, 134, 269, 102, 197, 700, 10, 137, 318, 6, 120, 165, 753, 352, 4, 82, 23, 117}, +{44, 201, 567, 116, 131, 224, 295, 662, 489, 268, 219, 31, 434, 144, 187, 276, 110, 384, 93, 261, 699, 137, 36, 442, 120, 1, 613, 30, 228, 64, 141, 244}, +{12, 15, 51, 23, 515, 37, 99, 13, 700, 0, 10, 117, 753, 38, 165, 82, 134, 120, 11, 453, 197, 64, 115, 569, 1, 629, 401, 22, 457, 474, 110, 153}, +{7, 135, 2, 92, 172, 14, 66, 140, 38, 52, 97, 46, 29, 74, 16, 324, 278, 226, 6, 87, 1, 571, 262, 5, 357, 232, 35, 380, 69, 314, 24, 330}, +{125, 386, 23, 963, 949, 60, 51, 391, 165, 221, 13, 197, 118, 21, 719, 193, 541, 421, 517, 150, 393, 7, 401, 453, 308, 5, 791, 551, 326, 558, 48, 173}, +{6, 85, 42, 25, 138, 222, 174, 235, 280, 256, 525, 289, 26, 214, 64, 746, 90, 32, 544, 65, 204, 19, 66, 337, 355, 95, 348, 415, 74, 29, 5, 312}, +{1, 14, 5, 50, 2, 67, 24, 0, 46, 69, 48, 21, 58, 103, 16, 12, 18, 38, 54, 96, 83, 7, 502, 45, 36, 181, 35, 9, 430, 28, 10, 155}, +{811, 351, 642, 180, 951, 752, 110, 638, 253, 10, 82, 352, 197, 341, 365, 564, 499, 854, 873, 55, 9, 417, 282, 901, 244, 22, 559, 143, 206, 141, 28, 898}, +{23, 13, 51, 15, 12, 453, 403, 165, 4, 515, 115, 719, 475, 457, 700, 523, 2, 21, 0, 99, 202, 197, 14, 5, 386, 753, 128, 401, 37, 308, 33, 117}, +{120, 13, 23, 77, 141, 1, 15, 93, 217, 82, 260, 51, 137, 202, 110, 515, 21, 180, 165, 5, 128, 102, 64, 351, 291, 700, 269, 352, 326, 203, 177, 0}, +{1, 5, 0, 22, 12, 2, 36, 21, 10, 23, 86, 13, 28, 51, 9, 128, 48, 14, 32, 50, 7, 3, 96, 137, 54, 4, 202, 49, 37, 65, 208, 323}, +{219, 98, 23, 127, 301, 51, 258, 308, 170, 910, 13, 165, 22, 105, 293, 616, 125, 242, 276, 401, 201, 395, 964, 115, 55, 284, 31, 374, 327, 206, 512, 900}, +{64, 180, 80, 165, 5, 237, 2, 250, 34, 58, 297, 61, 197, 17, 22, 29, 186, 498, 231, 445, 247, 3, 752, 311, 95, 32, 483, 153, 27, 45, 115, 469}, +{13, 77, 23, 33, 0, 2, 1, 64, 141, 51, 102, 10, 15, 3, 115, 40, 180, 6, 515, 128, 7, 22, 269, 202, 4, 217, 700, 5, 177, 117, 14, 165}, +{15, 120, 51, 515, 13, 450, 23, 700, 202, 153, 196, 753, 260, 64, 128, 141, 730, 4, 326, 386, 21, 523, 33, 318, 5, 457, 95, 32, 403, 1, 77, 269}, +{2, 1, 5, 29, 32, 45, 207, 263, 14, 425, 58, 72, 76, 21, 7, 408, 48, 46, 52, 186, 17, 292, 38, 6, 61, 89, 476, 50, 155, 720, 119, 3}, +{15, 515, 700, 753, 4, 13, 11, 5, 1, 23, 33, 21, 3, 141, 32, 2, 40, 180, 117, 64, 269, 202, 102, 197, 0, 165, 120, 51, 341, 352, 153, 12}, +{76, 5, 214, 129, 2, 123, 45, 710, 17, 249, 618, 460, 179, 32, 1, 257, 205, 519, 90, 207, 245, 184, 162, 61, 769, 209, 292, 106, 6, 29, 14, 128}, +{1, 15, 23, 13, 120, 141, 51, 515, 202, 21, 700, 165, 0, 180, 137, 2, 5, 77, 128, 93, 753, 260, 269, 197, 326, 33, 110, 352, 82, 102, 318, 48}, +{7, 2, 135, 14, 29, 87, 66, 52, 97, 172, 70, 112, 5, 58, 46, 337, 92, 16, 20, 43, 1, 38, 232, 155, 74, 294, 6, 461, 409, 151, 262, 32}, +{574, 187, 384, 926, 860, 110, 258, 434, 269, 531, 141, 244, 160, 261, 253, 116, 699, 959, 940, 717, 533, 36, 219, 31, 902, 661, 871, 295, 201, 352, 10, 260}, +{156, 354, 296, 1, 182, 586, 64, 379, 340, 937, 850, 698, 31, 48, 98, 44, 120, 18, 163, 23, 30, 658, 195, 125, 77, 284, 223, 291, 774, 481, 96, 39}, +{250, 80, 34, 472, 17, 495, 176, 469, 33, 194, 64, 483, 4, 297, 141, 14, 161, 27, 53, 667, 56, 833, 73, 527, 585, 231, 106, 51, 84, 814, 2, 59}, +{97, 7, 81, 140, 66, 92, 172, 192, 24, 298, 43, 6, 74, 69, 314, 426, 462, 14, 501, 16, 21, 508, 60, 189, 267, 232, 230, 104, 48, 20, 135, 330}, +{31, 44, 116, 144, 268, 393, 492, 434, 367, 489, 127, 98, 918, 0, 384, 9, 22, 206, 948, 105, 93, 203, 1, 456, 332, 940, 299, 28, 137, 49, 293, 125}, +{15, 128, 33, 3, 13, 51, 141, 1, 202, 64, 23, 2, 515, 120, 102, 0, 5, 82, 10, 700, 165, 197, 269, 153, 403, 110, 753, 137, 196, 318, 117, 12}, +{31, 98, 127, 9, 0, 105, 22, 28, 44, 512, 293, 395, 299, 1, 242, 49, 685, 763, 320, 599, 125, 116, 109, 276, 284, 95, 870, 159, 23, 456, 36, 900}, +{7, 24, 124, 1, 6, 97, 2, 69, 14, 18, 23, 92, 21, 67, 66, 16, 5, 484, 43, 20, 118, 65, 36, 22, 28, 0, 51, 140, 13, 71, 29, 150}, +{1, 64, 442, 303, 284, 349, 202, 141, 622, 67, 154, 447, 260, 44, 652, 429, 9, 335, 237, 919, 197, 98, 167, 33, 682, 269, 547, 77, 863, 411, 340, 201}, +{1, 15, 2, 141, 515, 0, 700, 13, 3, 180, 10, 753, 5, 64, 77, 33, 4, 6, 7, 197, 102, 269, 165, 23, 134, 11, 352, 341, 291, 349, 22, 120}, +{99, 139, 12, 453, 196, 277, 775, 40, 475, 33, 23, 401, 215, 51, 11, 14, 77, 111, 313, 130, 38, 211, 37, 266, 129, 15, 339, 153, 719, 3, 369, 515}, +{33, 77, 102, 4, 23, 128, 13, 141, 202, 64, 51, 0, 40, 59, 269, 115, 117, 137, 153, 1, 318, 11, 10, 177, 15, 134, 22, 90, 196, 2, 403, 32}, +{7, 2, 14, 58, 70, 112, 16, 5, 87, 38, 46, 52, 6, 128, 135, 1, 32, 21, 155, 29, 66, 64, 0, 97, 92, 186, 172, 294, 13, 23, 20, 37}, +{15, 13, 515, 1, 700, 2, 23, 0, 753, 5, 3, 4, 51, 10, 341, 115, 365, 180, 11, 33, 317, 77, 6, 7, 217, 12, 197, 165, 117, 9, 64, 102}, +{2, 1, 14, 29, 75, 69, 67, 6, 52, 46, 38, 24, 103, 220, 83, 25, 70, 87, 262, 74, 96, 267, 50, 366, 26, 16, 226, 394, 357, 66, 108, 19}, +{9, 105, 18, 39, 1, 0, 16, 557, 101, 272, 252, 890, 326, 49, 265, 21, 137, 100, 23, 938, 13, 310, 159, 5, 31, 24, 254, 51, 30, 128, 202, 132}, +{80, 209, 45, 61, 667, 17, 6, 106, 5, 2, 151, 29, 483, 255, 454, 833, 27, 311, 112, 19, 738, 378, 1, 58, 113, 26, 25, 469, 119, 887, 32, 64}, +{13, 23, 51, 15, 5, 1, 515, 0, 21, 2, 12, 141, 700, 165, 202, 115, 753, 32, 180, 4, 3, 197, 10, 120, 457, 9, 269, 128, 64, 341, 7, 33}, +{99, 12, 453, 277, 139, 157, 369, 474, 339, 51, 38, 23, 37, 196, 188, 401, 775, 111, 11, 313, 328, 475, 153, 266, 4, 471, 79, 40, 33, 629, 102, 14}, +{7, 92, 16, 232, 97, 140, 126, 14, 60, 107, 66, 35, 298, 387, 314, 104, 246, 462, 441, 150, 0, 38, 24, 2, 172, 357, 230, 330, 5, 633, 22, 289}, +{13, 77, 23, 202, 318, 141, 33, 4, 51, 269, 102, 177, 115, 403, 137, 2, 40, 494, 90, 11, 342, 128, 31, 117, 21, 32, 7, 12, 64, 134, 14, 10}, +{13, 2, 0, 23, 141, 1, 77, 3, 180, 33, 6, 64, 15, 10, 115, 51, 4, 5, 217, 197, 7, 165, 515, 102, 22, 11, 700, 269, 40, 352, 177, 14}, +{15, 515, 700, 753, 4, 11, 1, 93, 13, 5, 180, 110, 82, 21, 120, 23, 2, 33, 10, 141, 3, 165, 197, 102, 901, 0, 32, 341, 117, 40, 153, 12}, +{15, 515, 700, 753, 1, 13, 0, 2, 23, 4, 77, 51, 3, 5, 341, 291, 7, 33, 6, 115, 10, 9, 8, 217, 11, 177, 120, 180, 102, 165, 197, 365}, +{20, 43, 198, 325, 173, 904, 104, 234, 66, 147, 77, 319, 416, 422, 97, 426, 5, 0, 7, 450, 861, 202, 712, 725, 2, 32, 639, 376, 38, 324, 945, 315}, +{105, 0, 9, 28, 49, 301, 170, 1, 127, 159, 22, 16, 31, 98, 512, 623, 24, 109, 158, 395, 35, 68, 371, 65, 713, 55, 2, 242, 293, 21, 44, 18}, +{213, 88, 689, 466, 230, 30, 321, 435, 699, 352, 217, 201, 795, 831, 144, 854, 1, 443, 96, 539, 530, 840, 418, 251, 855, 190, 93, 100, 669, 31, 957, 662}, +{130, 453, 47, 196, 4, 57, 14, 59, 236, 711, 51, 153, 730, 77, 412, 381, 23, 202, 108, 128, 361, 13, 283, 117, 11, 719, 200, 46, 34, 78, 210, 2}, +{1, 2, 5, 14, 0, 50, 36, 22, 38, 46, 65, 67, 12, 86, 114, 28, 103, 29, 208, 7, 10, 128, 21, 83, 218, 23, 96, 54, 194, 6, 133, 51}, +{6, 26, 74, 19, 165, 453, 14, 730, 1, 125, 197, 50, 29, 51, 138, 357, 13, 2, 108, 391, 70, 719, 46, 457, 47, 500, 386, 262, 112, 23, 235, 52}, +{9, 10, 376, 20, 43, 0, 49, 18, 30, 120, 2, 33, 325, 104, 501, 470, 77, 788, 725, 102, 523, 39, 858, 5, 904, 414, 174, 55, 137, 37, 342, 13}, +{15, 515, 700, 753, 0, 1, 13, 23, 51, 77, 120, 202, 341, 82, 5, 4, 9, 260, 2, 137, 141, 128, 115, 351, 901, 8, 180, 10, 197, 21, 450, 33}, +{105, 131, 272, 578, 9, 49, 371, 219, 159, 616, 286, 320, 224, 187, 716, 98, 28, 22, 0, 623, 127, 258, 910, 737, 385, 31, 239, 347, 254, 109, 424, 95}, +{457, 51, 13, 23, 961, 12, 719, 99, 453, 15, 4, 515, 165, 401, 629, 3, 700, 11, 17, 14, 2, 37, 753, 41, 57, 569, 38, 45, 0, 33, 5, 32}, +{202, 120, 5, 33, 318, 77, 450, 102, 1, 260, 403, 128, 494, 21, 165, 13, 269, 12, 326, 23, 342, 523, 402, 2, 817, 64, 15, 141, 125, 82, 457, 475}, +{141, 269, 352, 217, 180, 64, 349, 137, 202, 160, 317, 15, 372, 515, 700, 752, 318, 753, 244, 13, 437, 291, 165, 864, 22, 237, 5, 82, 954, 21, 77, 418}, +{70, 29, 2, 145, 74, 112, 26, 6, 75, 52, 19, 66, 632, 1, 87, 220, 5, 135, 163, 287, 307, 25, 226, 7, 58, 396, 294, 278, 113, 409, 69, 151}, +{82, 351, 317, 15, 752, 180, 898, 352, 141, 901, 515, 341, 10, 700, 365, 1, 753, 498, 0, 217, 253, 115, 55, 854, 33, 5, 143, 32, 21, 160, 36, 197}, +{39, 9, 310, 254, 0, 30, 101, 49, 252, 272, 100, 265, 105, 455, 159, 557, 190, 333, 286, 688, 18, 166, 1, 158, 709, 16, 625, 627, 31, 131, 327, 329}, +{2, 58, 29, 5, 1, 151, 186, 52, 70, 45, 7, 549, 14, 75, 112, 400, 113, 155, 61, 46, 227, 163, 311, 315, 66, 6, 307, 27, 17, 220, 287, 74}, +{141, 217, 13, 21, 352, 23, 269, 77, 180, 115, 317, 64, 202, 15, 349, 137, 5, 51, 165, 291, 318, 752, 372, 4, 0, 102, 33, 365, 197, 32, 341, 125}, +{68, 35, 0, 9, 65, 101, 149, 124, 24, 154, 175, 16, 28, 7, 67, 1, 18, 189, 114, 398, 55, 14, 345, 39, 118, 133, 69, 2, 230, 429, 71, 283}, +{66, 7, 29, 2, 112, 52, 20, 43, 97, 151, 74, 192, 135, 5, 173, 525, 337, 45, 145, 58, 415, 25, 14, 32, 644, 70, 544, 226, 222, 21, 6, 580}, +{31, 125, 44, 22, 116, 299, 242, 55, 1, 170, 64, 36, 479, 870, 456, 685, 10, 599, 558, 0, 268, 506, 28, 740, 23, 903, 492, 164, 393, 206, 2, 86}, +{188, 11, 79, 12, 99, 377, 94, 33, 542, 339, 40, 474, 111, 37, 4, 51, 102, 453, 139, 775, 13, 475, 23, 961, 277, 471, 134, 57, 431, 266, 115, 117}, +{658, 698, 340, 98, 296, 303, 1, 31, 850, 363, 156, 919, 44, 774, 586, 385, 120, 77, 82, 10, 223, 30, 354, 291, 23, 914, 478, 87, 260, 163, 48, 13}, +{15, 515, 700, 753, 82, 4, 1, 13, 901, 33, 197, 11, 5, 10, 23, 165, 2, 0, 180, 3, 21, 77, 51, 120, 365, 115, 217, 40, 117, 102, 32, 401}, +{15, 515, 700, 753, 4, 11, 5, 13, 1, 141, 3, 180, 23, 202, 21, 2, 269, 64, 165, 33, 40, 32, 0, 318, 120, 128, 12, 197, 117, 352, 51, 17}, +{91, 6, 233, 85, 370, 718, 81, 65, 25, 256, 63, 343, 42, 74, 235, 123, 138, 511, 397, 249, 26, 194, 650, 355, 64, 87, 544, 18, 90, 643, 66, 214}, +{23, 13, 202, 51, 21, 120, 1, 5, 141, 128, 450, 64, 318, 403, 15, 137, 260, 33, 12, 48, 32, 31, 125, 494, 269, 102, 165, 515, 77, 2, 197, 14}, +{180, 317, 365, 341, 752, 217, 115, 352, 901, 482, 372, 498, 1, 141, 15, 253, 515, 244, 2, 700, 0, 21, 13, 82, 23, 4, 579, 351, 753, 291, 269, 77}, +{13, 115, 197, 341, 9, 352, 468, 237, 64, 498, 23, 165, 22, 509, 901, 546, 482, 180, 28, 569, 317, 51, 365, 873, 391, 95, 86, 217, 49, 837, 752, 706}, +{13, 23, 51, 1, 141, 5, 165, 202, 21, 120, 64, 125, 180, 15, 2, 33, 197, 115, 128, 32, 260, 269, 12, 82, 4, 515, 137, 7, 318, 93, 0, 700}, +{214, 289, 90, 174, 874, 6, 138, 280, 65, 81, 64, 85, 355, 751, 194, 233, 312, 348, 835, 91, 0, 32, 343, 636, 249, 29, 875, 288, 519, 104, 247, 74}, +{15, 515, 700, 753, 4, 5, 11, 13, 1, 33, 23, 21, 2, 3, 102, 32, 141, 77, 180, 117, 31, 64, 0, 40, 134, 196, 120, 352, 12, 44, 197, 6}, +{33, 15, 13, 515, 117, 23, 700, 217, 134, 753, 0, 51, 153, 77, 141, 2, 4, 64, 196, 1, 3, 180, 10, 115, 5, 102, 6, 11, 22, 202, 165, 7}, +{15, 515, 700, 753, 33, 4, 77, 102, 1, 40, 13, 117, 11, 115, 134, 5, 21, 153, 23, 217, 3, 32, 2, 317, 120, 196, 180, 141, 51, 12, 59, 260}, +{15, 515, 700, 753, 13, 0, 1, 23, 2, 217, 51, 3, 4, 5, 8, 317, 115, 9, 341, 10, 202, 180, 6, 365, 7, 82, 457, 22, 120, 901, 33, 291}, +{7, 2, 135, 20, 97, 14, 66, 52, 337, 673, 192, 29, 43, 355, 353, 5, 16, 294, 107, 376, 147, 226, 331, 560, 64, 470, 222, 104, 415, 32, 4, 324}, +{195, 132, 142, 167, 146, 77, 363, 271, 121, 354, 202, 120, 647, 178, 786, 212, 687, 0, 101, 878, 16, 522, 60, 5, 450, 411, 35, 55, 98, 639, 259, 318}, +{202, 77, 20, 0, 318, 66, 104, 128, 102, 269, 177, 43, 33, 7, 216, 291, 494, 5, 2, 342, 74, 173, 97, 112, 450, 22, 337, 10, 234, 52, 64, 678}, +{107, 362, 612, 356, 359, 97, 414, 43, 259, 20, 392, 7, 298, 147, 819, 683, 465, 173, 729, 660, 319, 14, 5, 779, 581, 595, 246, 35, 501, 92, 0, 230}, +{6, 165, 14, 453, 13, 51, 19, 23, 386, 457, 74, 391, 308, 2, 26, 401, 47, 758, 603, 108, 719, 366, 1, 29, 309, 730, 324, 197, 133, 70, 115, 867}, +{179, 72, 205, 180, 247, 245, 4, 490, 352, 59, 317, 152, 79, 498, 94, 217, 148, 76, 752, 864, 11, 216, 141, 405, 89, 452, 197, 111, 497, 188, 37, 21}, +{107, 7, 298, 314, 14, 359, 32, 392, 232, 279, 172, 97, 60, 581, 387, 126, 121, 0, 534, 493, 356, 92, 441, 95, 13, 21, 35, 147, 22, 5, 16, 362}, +{156, 271, 354, 586, 360, 132, 591, 195, 121, 18, 340, 1, 5, 13, 21, 48, 668, 446, 23, 463, 296, 658, 60, 55, 407, 698, 146, 70, 626, 51, 163, 24}, +{13, 23, 51, 4, 0, 12, 457, 15, 11, 453, 2, 515, 5, 1, 99, 10, 115, 165, 700, 475, 401, 403, 3, 961, 40, 14, 37, 753, 719, 32, 64, 569}, +{48, 125, 21, 165, 13, 221, 23, 763, 423, 508, 197, 5, 98, 92, 193, 16, 441, 386, 64, 314, 293, 457, 391, 140, 49, 60, 102, 693, 683, 51, 35, 867}, +{202, 77, 120, 450, 5, 318, 1, 494, 0, 195, 18, 132, 523, 403, 326, 604, 354, 260, 121, 576, 203, 167, 234, 817, 682, 49, 35, 615, 21, 20, 13, 102}, +{39, 9, 166, 30, 0, 101, 158, 68, 404, 190, 333, 274, 252, 310, 88, 100, 49, 28, 344, 35, 21, 22, 419, 131, 438, 1, 16, 65, 530, 694, 124, 10}, +{15, 515, 700, 753, 110, 4, 1, 11, 165, 180, 93, 13, 82, 5, 2, 197, 33, 120, 0, 3, 10, 23, 21, 115, 901, 217, 341, 77, 317, 51, 32, 117}, +{2, 29, 1, 14, 6, 52, 5, 46, 50, 26, 70, 19, 103, 58, 38, 67, 96, 262, 516, 309, 218, 133, 108, 27, 75, 17, 112, 114, 24, 487, 331, 83}, +{120, 77, 15, 13, 1, 141, 260, 23, 515, 217, 110, 51, 137, 700, 317, 202, 165, 291, 180, 21, 753, 128, 0, 177, 326, 93, 450, 82, 64, 269, 197, 5}, +{255, 59, 554, 297, 183, 56, 33, 444, 108, 358, 123, 196, 269, 122, 77, 153, 57, 177, 117, 730, 19, 467, 605, 130, 128, 50, 275, 4, 291, 475, 134, 133}, +{13, 23, 51, 12, 153, 14, 117, 120, 165, 134, 99, 401, 38, 453, 15, 128, 197, 719, 64, 515, 475, 403, 37, 33, 196, 700, 40, 125, 5, 0, 54, 2}, +{64, 33, 174, 348, 95, 108, 467, 554, 56, 0, 25, 306, 233, 6, 63, 511, 343, 120, 13, 85, 29, 561, 543, 707, 319, 180, 899, 355, 77, 49, 256, 18}, +{120, 260, 51, 23, 77, 15, 202, 1, 93, 82, 141, 450, 13, 326, 515, 137, 21, 5, 64, 33, 110, 700, 128, 165, 318, 203, 269, 102, 351, 753, 197, 125}, +{15, 515, 700, 753, 4, 13, 11, 1, 5, 21, 23, 2, 33, 64, 3, 180, 32, 141, 22, 102, 77, 0, 10, 93, 82, 352, 117, 40, 341, 31, 165, 6}, +{15, 515, 700, 753, 341, 13, 23, 141, 33, 1, 0, 217, 4, 77, 180, 10, 82, 351, 51, 137, 5, 64, 9, 317, 21, 11, 102, 40, 260, 202, 854, 115}, +{105, 272, 131, 22, 327, 286, 28, 239, 320, 9, 109, 578, 219, 49, 98, 224, 95, 159, 538, 371, 616, 127, 187, 64, 713, 55, 0, 170, 168, 258, 716, 623}, +{16, 18, 68, 35, 24, 60, 71, 118, 92, 126, 0, 9, 101, 191, 7, 55, 154, 175, 212, 14, 167, 150, 302, 28, 375, 1, 107, 124, 346, 273, 21, 108}, +{20, 147, 43, 470, 376, 142, 904, 178, 427, 798, 0, 595, 198, 325, 858, 319, 61, 202, 173, 97, 5, 422, 14, 22, 107, 259, 32, 49, 887, 77, 414, 392}, +{13, 23, 51, 12, 33, 15, 99, 64, 128, 515, 453, 202, 117, 153, 37, 102, 700, 40, 134, 196, 120, 0, 2, 753, 141, 14, 38, 3, 82, 403, 77, 21}, +{383, 17, 62, 136, 84, 119, 56, 440, 3, 504, 240, 80, 378, 129, 123, 548, 106, 128, 4, 11, 14, 555, 162, 32, 184, 361, 59, 64, 205, 5, 469, 57}, +{70, 1, 48, 652, 5, 638, 846, 888, 21, 349, 269, 260, 340, 562, 767, 761, 163, 883, 774, 141, 125, 518, 591, 0, 23, 9, 87, 13, 371, 303, 622, 31}, +{66, 135, 6, 97, 74, 278, 69, 7, 14, 324, 267, 172, 2, 140, 462, 1, 357, 38, 808, 550, 92, 841, 189, 29, 16, 25, 298, 87, 75, 204, 24, 335}, +{51, 23, 33, 13, 102, 40, 12, 128, 64, 77, 10, 202, 0, 196, 117, 4, 14, 99, 134, 453, 65, 153, 11, 475, 139, 403, 22, 141, 86, 2, 21, 15}, +{88, 100, 264, 166, 274, 435, 772, 1, 382, 921, 96, 478, 30, 438, 639, 909, 897, 521, 190, 466, 960, 410, 9, 144, 530, 418, 31, 329, 265, 691, 778, 93}, +{62, 440, 136, 56, 84, 3, 504, 548, 555, 383, 4, 17, 129, 128, 507, 361, 123, 59, 119, 162, 14, 57, 152, 328, 161, 11, 202, 495, 184, 27, 80, 215}, +{911, 617, 332, 959, 206, 141, 253, 244, 282, 384, 110, 120, 10, 260, 352, 143, 951, 811, 269, 373, 160, 417, 93, 531, 728, 203, 434, 940, 137, 55, 36, 717}, +{120, 15, 260, 141, 77, 1, 515, 82, 700, 351, 33, 23, 450, 13, 110, 326, 64, 217, 269, 753, 203, 137, 102, 5, 165, 21, 51, 291, 93, 177, 373, 128}, +{15, 515, 700, 753, 0, 1, 2, 23, 13, 51, 5, 9, 82, 901, 180, 8, 3, 4, 120, 6, 7, 141, 93, 12, 197, 341, 10, 33, 115, 730, 64, 125}, +{7, 104, 97, 107, 356, 232, 66, 560, 298, 289, 14, 707, 38, 568, 359, 64, 20, 0, 65, 324, 22, 214, 92, 32, 192, 5, 387, 43, 712, 90, 172, 95}, +{6, 1, 2, 66, 67, 14, 74, 24, 108, 29, 69, 83, 458, 7, 25, 38, 135, 103, 36, 150, 451, 114, 52, 594, 75, 65, 380, 18, 267, 602, 19, 278}, +{13, 23, 51, 12, 115, 21, 202, 5, 457, 15, 4, 1, 64, 719, 0, 403, 2, 3, 453, 165, 99, 141, 401, 128, 32, 515, 10, 37, 523, 197, 120, 700}, +{57, 59, 4, 11, 412, 381, 77, 53, 421, 291, 250, 368, 99, 14, 27, 369, 803, 283, 23, 108, 403, 19, 339, 210, 0, 401, 12, 444, 236, 40, 361, 736}, +{15, 515, 700, 1, 0, 753, 2, 13, 23, 5, 51, 180, 3, 115, 6, 7, 457, 4, 9, 8, 12, 82, 197, 165, 141, 901, 120, 719, 33, 64, 21, 22}, +{64, 95, 180, 247, 929, 146, 90, 126, 197, 32, 237, 60, 288, 165, 316, 92, 5, 13, 77, 7, 217, 955, 522, 22, 16, 314, 132, 4, 317, 10, 312, 86}, +{15, 1, 120, 13, 23, 515, 0, 51, 700, 180, 141, 2, 5, 202, 21, 260, 753, 165, 137, 33, 77, 110, 197, 128, 326, 7, 450, 4, 102, 9, 269, 12}, +{14, 2, 16, 46, 1, 7, 24, 69, 75, 35, 38, 50, 29, 220, 52, 140, 267, 67, 18, 54, 70, 309, 5, 60, 92, 189, 171, 87, 71, 163, 58, 0}, +{31, 98, 127, 44, 9, 299, 0, 276, 293, 284, 116, 49, 935, 599, 105, 22, 456, 201, 28, 1, 39, 125, 242, 137, 371, 144, 131, 492, 159, 272, 51, 395}, +{6, 27, 151, 53, 573, 445, 297, 113, 26, 73, 436, 19, 491, 250, 396, 315, 45, 112, 145, 58, 614, 881, 25, 34, 611, 200, 17, 80, 70, 5, 138, 631}, +{32, 693, 81, 788, 90, 804, 403, 56, 494, 21, 84, 397, 202, 65, 18, 77, 64, 681, 214, 725, 523, 784, 526, 33, 102, 825, 240, 0, 115, 241, 817, 91}, +{24, 7, 14, 2, 18, 16, 65, 0, 108, 149, 28, 69, 1, 71, 154, 36, 124, 35, 67, 140, 189, 429, 92, 68, 66, 22, 55, 118, 302, 150, 9, 6}, +{0, 68, 9, 35, 65, 101, 189, 212, 114, 67, 124, 69, 1, 154, 149, 39, 230, 64, 252, 16, 88, 702, 103, 100, 18, 336, 28, 329, 520, 83, 30, 755}, +{5, 2, 186, 29, 61, 45, 17, 1, 52, 48, 58, 171, 155, 227, 80, 209, 311, 21, 14, 46, 50, 106, 243, 513, 334, 502, 496, 38, 3, 6, 32, 592}, +{15, 515, 700, 753, 13, 1, 2, 0, 3, 4, 5, 23, 341, 11, 10, 33, 6, 51, 165, 117, 153, 7, 180, 12, 365, 901, 77, 569, 197, 115, 64, 9}, +{13, 15, 23, 515, 0, 51, 1, 700, 4, 2, 753, 10, 3, 5, 12, 77, 33, 961, 165, 457, 197, 11, 115, 9, 22, 102, 40, 403, 202, 21, 14, 59}, +{15, 515, 700, 753, 13, 0, 1, 23, 2, 33, 102, 5, 4, 10, 9, 3, 51, 115, 77, 7, 6, 341, 12, 11, 217, 40, 457, 196, 180, 165, 8, 523}, +{166, 39, 30, 274, 190, 100, 333, 438, 530, 310, 88, 252, 0, 9, 539, 265, 1, 656, 404, 101, 625, 131, 778, 254, 31, 455, 676, 329, 724, 158, 21, 23}, +{734, 148, 94, 308, 431, 115, 37, 89, 111, 413, 79, 468, 197, 629, 341, 474, 569, 12, 13, 873, 179, 401, 11, 4, 180, 23, 205, 72, 59, 365, 134, 51}, +{539, 228, 224, 219, 816, 190, 30, 258, 871, 840, 669, 93, 406, 530, 957, 187, 160, 531, 748, 137, 131, 88, 863, 36, 728, 839, 44, 213, 352, 116, 202, 466}, +{393, 791, 125, 801, 730, 551, 386, 23, 31, 175, 93, 98, 51, 13, 144, 788, 126, 203, 21, 345, 116, 22, 949, 110, 575, 165, 326, 44, 0, 4, 60, 221}, +{13, 23, 77, 141, 0, 4, 51, 2, 33, 115, 64, 1, 10, 3, 6, 15, 11, 102, 7, 217, 180, 40, 515, 22, 128, 177, 202, 9, 700, 269, 165, 5}, +{2, 29, 7, 70, 52, 14, 1, 58, 112, 46, 75, 5, 171, 163, 87, 220, 307, 151, 186, 334, 38, 66, 155, 16, 69, 135, 278, 45, 262, 97, 6, 21}, +{88, 321, 213, 100, 230, 435, 689, 466, 1, 382, 30, 352, 217, 699, 410, 96, 795, 36, 921, 752, 190, 141, 144, 180, 44, 831, 317, 83, 443, 31, 840, 251}, +{363, 411, 101, 520, 354, 9, 195, 668, 132, 156, 447, 1, 905, 364, 18, 23, 765, 664, 146, 5, 360, 13, 121, 96, 98, 31, 252, 39, 100, 759, 264, 551}, +{13, 23, 51, 730, 12, 719, 453, 457, 401, 475, 5, 21, 403, 2, 0, 1, 15, 4, 3, 899, 99, 32, 165, 11, 515, 308, 197, 115, 6, 961, 700, 523}, +{72, 76, 89, 12, 37, 4, 308, 179, 38, 528, 90, 431, 54, 205, 148, 184, 401, 57, 152, 474, 23, 59, 51, 245, 428, 11, 32, 99, 405, 316, 257, 21}, +{376, 20, 43, 147, 470, 173, 97, 595, 107, 319, 414, 142, 819, 5, 729, 178, 858, 7, 427, 32, 426, 104, 14, 0, 392, 362, 259, 61, 230, 77, 560, 246}, +{202, 141, 269, 494, 318, 137, 51, 128, 403, 4, 217, 96, 77, 5, 64, 177, 291, 180, 15, 352, 102, 10, 33, 349, 2, 317, 0, 341, 120, 515, 21, 453}, +{77, 202, 33, 128, 102, 318, 494, 269, 13, 0, 117, 23, 342, 291, 403, 15, 134, 51, 153, 141, 177, 515, 82, 137, 196, 700, 203, 64, 22, 351, 753, 4}, +{253, 110, 951, 352, 499, 811, 10, 854, 180, 638, 244, 559, 642, 752, 564, 8, 141, 143, 417, 341, 901, 260, 206, 197, 922, 661, 93, 15, 498, 373, 165, 911}, +{141, 13, 23, 180, 4, 217, 5, 1, 269, 317, 21, 0, 2, 202, 115, 51, 352, 77, 3, 197, 64, 341, 318, 15, 291, 9, 137, 93, 32, 165, 515, 33}, +{9, 0, 18, 252, 16, 101, 68, 39, 24, 118, 35, 109, 158, 329, 28, 167, 60, 364, 333, 265, 49, 100, 22, 419, 553, 55, 1, 677, 71, 7, 212, 159}, +{28, 109, 9, 39, 0, 158, 49, 22, 168, 35, 55, 175, 1, 65, 67, 185, 194, 159, 289, 95, 272, 114, 30, 105, 86, 584, 36, 169, 254, 2, 83, 24}, +{15, 515, 13, 700, 1, 753, 2, 23, 0, 3, 4, 5, 33, 341, 11, 51, 6, 10, 197, 115, 901, 180, 77, 40, 102, 12, 365, 165, 141, 217, 7, 317}, +{173, 693, 104, 422, 5, 18, 61, 32, 102, 0, 20, 13, 784, 560, 33, 66, 397, 526, 49, 207, 29, 25, 510, 707, 65, 6, 11, 344, 21, 263, 81, 77}, +{23, 13, 386, 51, 308, 801, 719, 221, 401, 949, 21, 730, 165, 421, 102, 115, 125, 33, 341, 670, 468, 117, 770, 1, 120, 6, 197, 14, 403, 97, 67, 958}, +{0, 49, 105, 16, 28, 24, 159, 9, 158, 320, 1, 68, 35, 239, 170, 18, 109, 7, 55, 65, 2, 95, 301, 124, 347, 14, 21, 154, 22, 127, 286, 31}, +{2, 5, 1, 207, 45, 29, 32, 58, 76, 61, 6, 263, 292, 655, 72, 14, 17, 476, 7, 119, 52, 306, 70, 64, 21, 90, 186, 214, 106, 38, 3, 790}, +{21, 6, 125, 49, 13, 64, 715, 66, 115, 95, 197, 33, 22, 32, 204, 165, 56, 278, 0, 408, 241, 120, 4, 808, 681, 350, 263, 85, 81, 571, 135, 509}, +{612, 427, 325, 107, 202, 5, 376, 49, 64, 392, 403, 470, 21, 147, 31, 788, 494, 14, 362, 465, 858, 98, 20, 804, 518, 43, 845, 318, 125, 97, 725, 534}, +{32, 21, 76, 72, 2, 1, 14, 5, 241, 449, 89, 38, 350, 221, 155, 48, 50, 292, 37, 46, 45, 90, 270, 54, 17, 179, 214, 12, 148, 430, 476, 413}, +{24, 0, 28, 16, 7, 124, 35, 154, 14, 149, 65, 18, 9, 68, 55, 108, 175, 71, 2, 1, 22, 109, 92, 67, 484, 336, 118, 69, 302, 398, 570, 420}, +{1, 5, 14, 2, 48, 50, 38, 67, 46, 21, 0, 54, 45, 270, 281, 12, 24, 32, 155, 96, 513, 103, 290, 83, 61, 58, 36, 17, 37, 72, 69, 181}, +{13, 961, 569, 197, 37, 15, 23, 474, 515, 94, 148, 111, 12, 165, 629, 341, 700, 79, 901, 401, 51, 405, 753, 10, 134, 4, 115, 734, 873, 11, 89, 117}, +{33, 23, 102, 51, 13, 40, 77, 128, 64, 202, 141, 15, 4, 12, 0, 1, 2, 117, 22, 11, 10, 403, 153, 515, 99, 318, 137, 269, 139, 196, 700, 134}, +{0, 1, 24, 67, 9, 16, 18, 35, 28, 69, 103, 50, 5, 2, 65, 12, 83, 68, 7, 96, 14, 22, 21, 149, 75, 114, 13, 133, 23, 71, 218, 54}, +{384, 617, 940, 332, 855, 911, 206, 959, 434, 282, 141, 10, 93, 253, 244, 110, 144, 268, 120, 36, 352, 137, 417, 203, 116, 31, 44, 269, 160, 201, 143, 951}, +{30, 93, 473, 137, 31, 704, 450, 652, 190, 203, 800, 254, 166, 274, 326, 144, 269, 160, 127, 303, 120, 625, 88, 848, 110, 435, 77, 521, 349, 131, 340, 744}, +{53, 27, 73, 26, 19, 250, 297, 200, 25, 630, 17, 6, 611, 122, 34, 42, 714, 235, 472, 65, 436, 14, 80, 684, 690, 106, 45, 113, 680, 108, 64, 4}, +{15, 515, 1, 2, 700, 0, 753, 3, 5, 141, 180, 4, 13, 77, 33, 10, 217, 6, 7, 134, 11, 352, 197, 64, 165, 341, 317, 23, 12, 115, 102, 40}, +{254, 530, 39, 613, 688, 221, 30, 31, 438, 190, 228, 960, 1, 44, 141, 21, 180, 406, 23, 166, 9, 202, 13, 96, 137, 48, 131, 829, 317, 269, 393, 51}, +{9, 39, 28, 35, 30, 166, 158, 36, 0, 175, 101, 346, 364, 67, 49, 68, 168, 420, 88, 1, 194, 131, 100, 352, 55, 83, 190, 64, 137, 570, 86, 65}, +{62, 56, 3, 548, 555, 507, 440, 161, 34, 4, 215, 136, 162, 514, 361, 527, 17, 14, 211, 130, 328, 11, 383, 123, 84, 183, 38, 57, 184, 152, 205, 494}, +{92, 126, 107, 7, 356, 493, 97, 279, 359, 298, 16, 246, 35, 60, 14, 441, 362, 121, 43, 423, 5, 132, 392, 20, 508, 230, 199, 146, 232, 173, 150, 414}, +{15, 82, 141, 515, 291, 922, 349, 700, 217, 260, 372, 120, 351, 93, 77, 753, 318, 352, 373, 854, 1, 326, 269, 21, 13, 102, 144, 202, 64, 23, 203, 137}, +{141, 217, 352, 115, 180, 13, 269, 317, 752, 77, 23, 21, 341, 197, 5, 372, 244, 291, 9, 64, 51, 102, 4, 1, 365, 2, 165, 33, 3, 48, 237, 351}, +{78, 47, 390, 19, 130, 453, 108, 27, 711, 813, 730, 444, 412, 283, 196, 690, 123, 14, 128, 26, 250, 389, 650, 236, 200, 65, 51, 4, 34, 183, 297, 73}, +{34, 250, 297, 80, 472, 64, 495, 17, 311, 3, 148, 45, 667, 61, 176, 53, 243, 27, 90, 161, 469, 141, 483, 151, 62, 128, 29, 4, 58, 56, 5, 231}, +{51, 23, 33, 13, 551, 77, 102, 326, 421, 21, 523, 120, 5, 899, 453, 692, 202, 153, 308, 615, 115, 958, 450, 401, 791, 68, 221, 93, 475, 18, 403, 4}, +{98, 223, 393, 363, 411, 1, 478, 834, 664, 156, 284, 691, 447, 791, 914, 293, 354, 724, 697, 9, 807, 541, 759, 51, 18, 421, 48, 264, 948, 586, 195, 848}, +{7, 14, 107, 232, 16, 92, 2, 60, 46, 5, 359, 121, 24, 526, 220, 620, 135, 1, 172, 21, 126, 314, 132, 77, 18, 75, 32, 278, 12, 23, 52, 38}, +{32, 76, 2, 1, 21, 72, 241, 14, 5, 48, 292, 89, 476, 45, 720, 270, 179, 90, 17, 214, 148, 38, 50, 29, 129, 155, 350, 46, 290, 227, 123, 464}, +{15, 515, 700, 753, 13, 23, 33, 77, 51, 4, 102, 0, 32, 202, 1, 11, 128, 82, 117, 141, 40, 5, 110, 8, 3, 90, 137, 21, 10, 318, 403, 165}, +{66, 6, 69, 2, 1, 74, 14, 135, 278, 267, 380, 24, 29, 97, 67, 38, 103, 75, 7, 388, 324, 25, 52, 150, 87, 83, 189, 357, 335, 108, 204, 172}, +{152, 4, 339, 59, 79, 471, 188, 11, 77, 94, 128, 33, 529, 377, 12, 111, 102, 202, 452, 402, 216, 99, 13, 542, 51, 40, 474, 37, 64, 291, 23, 961}, +{15, 515, 700, 753, 1, 0, 196, 13, 33, 2, 77, 5, 23, 102, 3, 10, 9, 7, 217, 4, 6, 153, 117, 177, 14, 457, 115, 12, 40, 730, 11, 134}, +{17, 209, 45, 106, 207, 5, 255, 119, 62, 2, 61, 3, 263, 742, 306, 655, 425, 378, 32, 56, 29, 136, 84, 80, 311, 58, 186, 240, 243, 383, 14, 21}, +{120, 260, 450, 15, 1, 23, 817, 13, 515, 523, 326, 5, 700, 51, 82, 31, 202, 64, 21, 753, 318, 93, 32, 269, 98, 33, 351, 77, 102, 125, 457, 165}, +{116, 492, 268, 93, 23, 206, 203, 0, 551, 918, 13, 51, 8, 22, 417, 940, 120, 10, 499, 31, 949, 791, 125, 523, 165, 473, 341, 730, 421, 959, 401, 391}, +{15, 515, 700, 753, 165, 13, 0, 1, 197, 23, 4, 82, 120, 2, 180, 12, 260, 719, 8, 3, 386, 117, 5, 523, 901, 11, 341, 51, 10, 9, 141, 351}, +{14, 24, 69, 7, 2, 66, 108, 1, 67, 6, 36, 398, 18, 267, 150, 97, 29, 38, 83, 149, 65, 74, 28, 0, 189, 71, 388, 16, 273, 124, 46, 22}, +{330, 96, 523, 335, 367, 662, 141, 839, 1, 922, 372, 615, 244, 717, 269, 443, 418, 352, 403, 692, 217, 854, 752, 180, 36, 64, 498, 576, 349, 201, 98, 284}, +{184, 90, 257, 205, 245, 229, 57, 152, 769, 17, 524, 5, 32, 497, 45, 432, 619, 2, 452, 266, 4, 106, 1, 21, 179, 59, 76, 3, 460, 292, 381, 128}, +{7, 14, 16, 2, 46, 5, 70, 107, 87, 13, 58, 307, 92, 32, 38, 23, 202, 0, 172, 24, 18, 21, 60, 128, 77, 35, 20, 10, 9, 4, 171, 112}, +{7, 66, 140, 16, 14, 92, 97, 69, 267, 172, 189, 24, 380, 2, 35, 60, 298, 451, 230, 135, 314, 74, 150, 71, 38, 357, 6, 330, 67, 423, 21, 443}, +{121, 167, 354, 132, 18, 446, 147, 101, 212, 146, 407, 16, 55, 35, 647, 191, 20, 271, 199, 68, 60, 259, 463, 107, 9, 126, 363, 7, 195, 43, 14, 411}, +{76, 90, 179, 32, 205, 21, 184, 460, 257, 288, 45, 245, 316, 5, 57, 152, 241, 2, 358, 1, 229, 72, 524, 148, 48, 769, 17, 4, 12, 38, 14, 720}, +{147, 259, 178, 878, 427, 465, 581, 198, 786, 798, 142, 534, 325, 929, 20, 362, 35, 132, 107, 376, 43, 5, 279, 77, 49, 146, 70, 202, 590, 771, 33, 14}, +{473, 93, 450, 778, 141, 30, 855, 466, 144, 203, 330, 530, 88, 523, 459, 372, 201, 617, 839, 704, 254, 321, 934, 326, 39, 36, 82, 717, 332, 213, 559, 403}, +{523, 475, 51, 899, 730, 453, 23, 719, 403, 33, 457, 13, 421, 386, 4, 120, 117, 196, 102, 153, 15, 801, 450, 817, 515, 260, 202, 11, 700, 99, 165, 125}, +{15, 1, 13, 515, 0, 2, 700, 5, 23, 753, 4, 3, 341, 317, 10, 115, 180, 11, 33, 64, 217, 77, 117, 165, 197, 7, 6, 365, 9, 141, 102, 134}, +{19, 4, 119, 40, 33, 202, 27, 84, 102, 56, 77, 73, 504, 485, 26, 494, 757, 63, 862, 59, 23, 300, 25, 12, 128, 11, 5, 13, 342, 880, 469, 6}, +{32, 20, 2, 13, 5, 21, 23, 6, 12, 38, 43, 29, 64, 7, 95, 51, 61, 207, 48, 147, 90, 178, 17, 182, 49, 0, 115, 202, 52, 362, 37, 22}, +{339, 188, 11, 79, 4, 94, 377, 12, 99, 111, 542, 102, 37, 33, 474, 51, 471, 40, 453, 152, 77, 13, 59, 403, 342, 23, 117, 57, 475, 134, 128, 38}, +{34, 128, 283, 176, 495, 231, 318, 432, 503, 275, 529, 527, 161, 53, 3, 202, 56, 291, 585, 469, 73, 17, 14, 412, 57, 27, 80, 245, 250, 381, 402, 51}, +{15, 515, 13, 700, 1, 217, 141, 120, 23, 180, 753, 115, 365, 51, 317, 341, 77, 260, 0, 291, 110, 137, 202, 5, 21, 269, 64, 36, 349, 2, 4, 10}, +{13, 15, 961, 515, 700, 753, 4, 12, 2, 457, 3, 11, 197, 51, 37, 569, 115, 23, 5, 0, 99, 10, 1, 134, 6, 111, 165, 33, 72, 40, 38, 79}, +{15, 515, 700, 753, 13, 1, 0, 2, 23, 33, 5, 3, 10, 4, 9, 115, 7, 102, 6, 51, 12, 217, 77, 11, 40, 457, 569, 341, 117, 317, 14, 719}, +{5, 76, 2, 32, 292, 214, 45, 1, 129, 519, 123, 179, 90, 710, 17, 29, 460, 72, 14, 207, 21, 249, 58, 205, 464, 263, 618, 48, 6, 245, 3, 257}, +{72, 76, 32, 4, 21, 12, 38, 23, 99, 54, 89, 3, 14, 17, 51, 57, 11, 90, 13, 488, 179, 2, 59, 148, 45, 37, 5, 115, 401, 1, 10, 421}, +{98, 223, 393, 1, 834, 264, 284, 791, 724, 293, 478, 772, 697, 909, 363, 682, 905, 447, 541, 821, 411, 51, 421, 9, 807, 48, 765, 31, 730, 96, 386, 410}, +{341, 13, 509, 8, 23, 638, 165, 901, 762, 10, 569, 242, 391, 197, 873, 642, 506, 499, 629, 961, 15, 180, 116, 456, 206, 546, 417, 1, 338, 457, 515, 867}, +{1, 2, 5, 50, 14, 38, 46, 114, 0, 36, 29, 22, 218, 65, 86, 96, 137, 21, 133, 285, 12, 10, 323, 181, 17, 58, 51, 23, 67, 7, 28, 6}, +{481, 878, 202, 13, 5, 23, 182, 32, 269, 21, 1, 318, 77, 142, 557, 494, 141, 33, 640, 137, 70, 291, 2, 51, 260, 415, 929, 403, 120, 58, 4, 259}, +{15, 515, 700, 753, 1, 4, 13, 0, 2, 5, 341, 3, 11, 180, 134, 12, 10, 317, 197, 365, 33, 21, 23, 165, 117, 6, 77, 7, 217, 37, 32, 498}, +{25, 119, 19, 6, 26, 42, 27, 17, 4, 790, 45, 814, 2, 469, 483, 84, 122, 1, 0, 33, 32, 128, 76, 80, 611, 113, 73, 56, 5, 240, 202, 77}, +{14, 2, 7, 1, 24, 0, 65, 6, 16, 69, 67, 22, 124, 28, 108, 5, 18, 36, 86, 10, 38, 46, 66, 398, 289, 168, 12, 83, 21, 23, 610, 13}, +{51, 23, 128, 13, 15, 202, 12, 120, 33, 64, 141, 82, 10, 515, 0, 403, 700, 3, 1, 99, 117, 269, 153, 165, 753, 5, 318, 197, 102, 260, 2, 137}, +{16, 35, 24, 0, 9, 18, 7, 1, 68, 69, 50, 71, 103, 65, 67, 189, 133, 23, 28, 13, 60, 537, 149, 335, 75, 21, 64, 5, 114, 2, 12, 14}, +{754, 803, 133, 576, 880, 543, 2, 1, 657, 50, 14, 38, 46, 5, 29, 67, 218, 36, 58, 171, 52, 96, 24, 103, 775, 0, 114, 83, 181, 54, 65, 45}, +{21, 32, 5, 3, 2, 17, 14, 72, 76, 1, 12, 23, 38, 51, 4, 54, 10, 0, 89, 13, 99, 137, 45, 36, 421, 115, 543, 11, 22, 128, 221, 48}, +{434, 384, 268, 144, 855, 940, 617, 206, 332, 116, 93, 911, 959, 282, 203, 137, 141, 489, 44, 120, 10, 110, 244, 36, 98, 31, 269, 253, 367, 417, 160, 9}, +{15, 2, 1, 0, 13, 515, 5, 700, 3, 23, 180, 217, 141, 10, 753, 4, 117, 6, 77, 33, 64, 7, 11, 197, 352, 317, 341, 134, 165, 115, 12, 9}, +{2, 113, 6, 25, 1, 0, 29, 4, 7, 833, 5, 45, 32, 61, 128, 19, 77, 151, 74, 145, 64, 42, 14, 210, 655, 106, 59, 177, 27, 17, 21, 738}, +{116, 268, 918, 203, 551, 31, 8, 692, 206, 791, 403, 499, 417, 93, 940, 421, 0, 23, 22, 120, 13, 523, 44, 51, 299, 473, 959, 1, 10, 475, 202, 125}, +{107, 126, 132, 612, 362, 279, 20, 146, 259, 493, 199, 121, 590, 43, 660, 147, 35, 376, 939, 60, 941, 534, 683, 5, 0, 953, 16, 7, 49, 649, 595, 470}, +{15, 515, 700, 753, 13, 1, 0, 23, 2, 33, 77, 4, 3, 51, 5, 102, 115, 10, 9, 341, 6, 7, 11, 342, 217, 12, 120, 180, 40, 317, 141, 8}, +{53, 27, 17, 161, 469, 378, 73, 527, 19, 136, 383, 250, 495, 56, 862, 26, 62, 84, 80, 106, 200, 4, 34, 14, 440, 297, 3, 128, 585, 5, 129, 123}, +{17, 45, 209, 106, 5, 207, 243, 454, 119, 255, 2, 263, 186, 290, 29, 3, 21, 62, 425, 61, 84, 32, 58, 56, 48, 408, 655, 136, 306, 14, 742, 227}, +{4, 152, 59, 452, 128, 79, 216, 11, 339, 471, 529, 188, 94, 77, 202, 12, 291, 33, 318, 377, 99, 51, 23, 5, 402, 349, 32, 474, 102, 13, 205, 111}, +{15, 515, 700, 753, 1, 0, 2, 13, 3, 5, 23, 4, 180, 51, 115, 9, 6, 12, 7, 8, 197, 33, 10, 961, 901, 77, 141, 752, 110, 22, 120, 341}, +{951, 752, 638, 811, 351, 642, 180, 253, 10, 341, 197, 901, 110, 873, 8, 244, 15, 352, 165, 898, 143, 515, 564, 762, 499, 55, 365, 700, 82, 753, 141, 854}, +{6, 262, 197, 350, 74, 26, 115, 509, 841, 583, 165, 38, 21, 13, 47, 50, 235, 19, 33, 324, 453, 4, 308, 196, 138, 99, 64, 903, 675, 1, 223, 130}, +{125, 165, 391, 23, 386, 221, 21, 13, 558, 457, 51, 867, 197, 115, 401, 758, 77, 97, 308, 791, 7, 180, 48, 120, 963, 451, 743, 89, 603, 134, 403, 450}, +{1, 14, 2, 5, 16, 46, 7, 38, 58, 24, 50, 0, 69, 48, 35, 67, 54, 18, 12, 75, 21, 45, 513, 155, 430, 37, 270, 9, 61, 163, 223, 32}, +{23, 13, 51, 0, 12, 15, 4, 1, 115, 2, 515, 453, 10, 457, 5, 3, 202, 21, 165, 700, 403, 11, 37, 64, 77, 401, 9, 197, 753, 59, 475, 99}, +{129, 84, 17, 56, 27, 495, 19, 548, 80, 123, 162, 378, 3, 504, 161, 469, 618, 73, 40, 53, 4, 26, 205, 184, 106, 183, 62, 6, 257, 128, 862, 12}, +{28, 9, 22, 49, 109, 1, 67, 0, 39, 55, 168, 158, 83, 36, 35, 86, 420, 194, 185, 159, 95, 105, 69, 208, 272, 103, 50, 114, 2, 254, 169, 30}, +{242, 391, 8, 456, 116, 13, 23, 492, 341, 165, 867, 51, 499, 457, 479, 638, 338, 509, 719, 10, 1, 642, 417, 762, 401, 93, 206, 268, 901, 569, 22, 197}, +{211, 162, 248, 130, 57, 4, 41, 556, 507, 266, 183, 152, 305, 361, 11, 129, 62, 229, 38, 471, 514, 313, 157, 300, 377, 3, 440, 128, 123, 328, 339, 59}, +{7, 92, 97, 16, 298, 140, 60, 126, 14, 35, 279, 314, 232, 246, 43, 230, 508, 173, 71, 107, 423, 24, 150, 779, 20, 189, 66, 18, 607, 21, 0, 653}, +{15, 515, 700, 753, 1, 0, 2, 13, 23, 5, 3, 180, 51, 901, 6, 4, 7, 12, 9, 115, 8, 457, 165, 82, 120, 197, 10, 64, 141, 341, 22, 117}, +{0, 18, 403, 25, 523, 74, 6, 24, 42, 91, 22, 102, 13, 51, 49, 193, 475, 681, 95, 85, 730, 64, 899, 397, 273, 750, 247, 673, 32, 805, 757, 288}, +{56, 0, 18, 65, 33, 554, 84, 343, 64, 6, 90, 561, 22, 19, 899, 108, 27, 63, 289, 475, 240, 467, 370, 32, 233, 214, 24, 123, 95, 287, 28, 194}, +{31, 98, 127, 9, 0, 44, 293, 105, 395, 299, 49, 242, 28, 22, 599, 116, 1, 284, 276, 125, 456, 685, 763, 159, 272, 623, 23, 935, 393, 144, 201, 137}, +{1, 5, 2, 14, 38, 46, 50, 48, 21, 7, 58, 45, 270, 61, 155, 171, 0, 290, 69, 32, 29, 54, 67, 16, 24, 666, 663, 17, 37, 75, 502, 52}, +{23, 51, 13, 453, 457, 12, 719, 4, 15, 99, 401, 2, 961, 3, 11, 730, 475, 515, 0, 1, 165, 115, 629, 700, 14, 17, 403, 40, 5, 33, 37, 64}, +{968, 967, 966, 965, 964, 963, 962, 961, 960, 959, 958, 957, 956, 955, 954, 953, 952, 951, 950, 949, 948, 947, 946, 945, 944, 943, 942, 941, 940, 939, 938, 937}, +{2, 1, 14, 29, 67, 103, 6, 46, 52, 75, 24, 133, 38, 218, 83, 309, 36, 108, 70, 114, 96, 5, 238, 74, 25, 26, 220, 236, 65, 50, 69, 87}, +{7, 71, 16, 92, 24, 60, 14, 97, 150, 140, 35, 189, 149, 298, 18, 230, 43, 508, 2, 423, 69, 0, 38, 314, 66, 279, 399, 517, 251, 20, 232, 273}, +{23, 1, 120, 51, 13, 202, 77, 141, 260, 21, 15, 5, 128, 82, 2, 450, 269, 165, 102, 318, 48, 32, 137, 515, 125, 64, 12, 115, 351, 180, 33, 7}, +{77, 13, 33, 23, 64, 51, 4, 102, 141, 128, 40, 1, 2, 202, 0, 6, 177, 115, 137, 15, 59, 10, 11, 7, 269, 22, 515, 180, 318, 3, 700, 95}, +{101, 9, 18, 363, 264, 520, 411, 604, 676, 682, 905, 271, 16, 821, 167, 0, 621, 364, 39, 100, 121, 118, 166, 781, 647, 252, 1, 848, 447, 265, 404, 60}, +{144, 203, 326, 382, 166, 418, 93, 88, 96, 822, 1, 141, 859, 77, 744, 438, 110, 269, 921, 367, 521, 274, 100, 39, 494, 120, 403, 473, 217, 576, 13, 291}, +{13, 21, 180, 125, 5, 23, 191, 32, 18, 16, 146, 199, 115, 24, 165, 118, 0, 225, 22, 1, 60, 197, 64, 901, 375, 241, 48, 12, 408, 71, 522, 818}, +{15, 515, 700, 753, 13, 0, 23, 8, 1, 51, 82, 102, 2, 33, 4, 9, 180, 165, 5, 77, 10, 110, 12, 197, 120, 260, 18, 326, 351, 403, 22, 457}, +{33, 77, 102, 64, 13, 23, 128, 51, 141, 202, 1, 40, 0, 2, 117, 10, 15, 4, 6, 318, 269, 134, 22, 515, 180, 115, 177, 153, 137, 196, 3, 700}, +{174, 544, 104, 525, 74, 0, 151, 25, 6, 624, 29, 66, 2, 636, 81, 45, 204, 177, 64, 416, 7, 644, 5, 138, 222, 319, 355, 77, 22, 122, 789, 216}, +{141, 304, 372, 352, 291, 947, 177, 269, 128, 954, 77, 349, 217, 202, 64, 318, 498, 437, 102, 864, 86, 13, 115, 180, 137, 5, 210, 197, 32, 950, 678, 7}, +{161, 200, 53, 17, 714, 27, 34, 73, 472, 62, 585, 56, 440, 383, 136, 78, 527, 19, 4, 3, 106, 361, 14, 250, 80, 514, 377, 84, 322, 390, 862, 548}, +{32, 76, 72, 21, 38, 14, 89, 54, 12, 37, 2, 241, 5, 428, 17, 1, 181, 221, 350, 45, 3, 4, 449, 90, 148, 179, 99, 292, 794, 770, 477, 46}, +{33, 23, 128, 64, 141, 13, 77, 51, 102, 202, 2, 15, 1, 3, 40, 10, 5, 153, 269, 515, 165, 0, 117, 196, 180, 318, 6, 700, 137, 134, 120, 22}, +{96, 137, 30, 0, 9, 39, 840, 202, 669, 406, 141, 530, 613, 1, 180, 88, 22, 160, 679, 576, 28, 403, 31, 219, 49, 228, 829, 100, 36, 15, 10, 856}, +{180, 141, 352, 1, 15, 752, 115, 0, 217, 365, 2, 515, 13, 901, 341, 317, 23, 4, 197, 700, 269, 5, 3, 31, 753, 244, 21, 165, 253, 202, 51, 44}, +{1, 2, 67, 0, 28, 50, 83, 65, 14, 46, 103, 114, 24, 38, 36, 9, 69, 5, 18, 7, 22, 133, 55, 218, 16, 124, 29, 54, 96, 160, 12, 480}, +{180, 115, 352, 317, 365, 217, 752, 901, 141, 15, 341, 1, 515, 253, 700, 0, 753, 873, 2, 197, 31, 137, 165, 244, 4, 120, 160, 44, 98, 5, 202, 3}, +{5, 32, 347, 49, 13, 21, 95, 713, 23, 1, 77, 33, 60, 64, 107, 4, 126, 928, 296, 850, 0, 241, 197, 102, 652, 195, 180, 534, 165, 153, 379, 10}, +{341, 180, 365, 901, 317, 115, 15, 752, 515, 700, 217, 873, 753, 82, 0, 110, 197, 141, 951, 165, 1, 564, 13, 351, 253, 12, 10, 3, 2, 4, 308, 244}, +{17, 45, 21, 3, 106, 5, 155, 38, 227, 32, 2, 209, 62, 54, 12, 243, 14, 181, 552, 587, 46, 540, 207, 794, 37, 48, 430, 119, 255, 221, 770, 29}, +{16, 24, 35, 18, 7, 0, 50, 1, 9, 14, 75, 69, 2, 5, 12, 21, 60, 13, 67, 71, 23, 48, 10, 108, 223, 181, 189, 103, 46, 64, 92, 51}, +{127, 13, 98, 165, 308, 23, 286, 293, 258, 51, 219, 395, 197, 115, 301, 401, 31, 391, 22, 105, 457, 170, 239, 276, 55, 338, 629, 116, 180, 479, 509, 569}, +{539, 213, 748, 840, 957, 669, 30, 466, 88, 217, 144, 251, 863, 190, 137, 93, 230, 228, 679, 352, 317, 203, 617, 321, 258, 530, 160, 219, 96, 831, 816, 689}, +{5, 48, 1, 21, 2, 14, 0, 36, 12, 38, 32, 54, 430, 181, 50, 270, 72, 99, 281, 45, 17, 10, 46, 22, 37, 218, 67, 3, 290, 76, 23, 51}, +{13, 23, 0, 4, 33, 51, 2, 115, 141, 1, 77, 217, 180, 10, 9, 317, 3, 102, 11, 5, 15, 197, 7, 202, 22, 165, 40, 64, 515, 6, 341, 31}, +{13, 15, 117, 515, 23, 12, 37, 134, 165, 700, 38, 54, 457, 753, 51, 64, 153, 197, 14, 10, 33, 82, 961, 0, 99, 89, 115, 719, 141, 3, 4, 1}, +{5, 21, 2, 3, 1, 32, 14, 12, 48, 17, 0, 10, 51, 23, 38, 22, 4, 72, 13, 54, 36, 45, 137, 76, 99, 114, 86, 37, 11, 64, 540, 430}, +{202, 128, 77, 318, 291, 33, 269, 102, 275, 141, 494, 342, 40, 678, 0, 177, 20, 210, 402, 7, 4, 5, 137, 6, 13, 450, 403, 32, 49, 120, 23, 22}, +{1, 2, 24, 14, 67, 46, 69, 50, 38, 103, 16, 18, 75, 35, 83, 29, 52, 96, 5, 108, 0, 7, 54, 71, 149, 394, 236, 309, 70, 133, 220, 58}, +{15, 515, 1, 700, 0, 2, 753, 13, 23, 5, 180, 3, 51, 4, 165, 457, 12, 197, 115, 6, 7, 21, 9, 141, 8, 901, 33, 82, 120, 77, 10, 110}, +{0, 28, 65, 14, 67, 2, 124, 24, 1, 9, 7, 69, 55, 154, 36, 16, 46, 114, 175, 35, 83, 22, 429, 18, 109, 149, 68, 189, 108, 336, 251, 133}, +{56, 162, 403, 3, 129, 775, 99, 161, 17, 40, 527, 33, 880, 4, 14, 128, 475, 12, 548, 23, 102, 202, 361, 117, 34, 184, 383, 200, 183, 196, 64, 53}, +{151, 2, 29, 58, 112, 45, 186, 113, 5, 70, 52, 1, 311, 6, 315, 66, 61, 7, 74, 27, 631, 17, 80, 87, 287, 243, 209, 227, 14, 491, 19, 869}, +{6, 1, 74, 2, 75, 29, 25, 66, 26, 70, 52, 138, 67, 324, 357, 42, 19, 220, 14, 85, 87, 108, 38, 451, 309, 103, 24, 69, 380, 135, 114, 65}, +{15, 515, 700, 13, 23, 0, 1, 120, 753, 51, 180, 2, 260, 202, 5, 141, 77, 102, 9, 450, 115, 21, 197, 165, 7, 137, 110, 33, 12, 269, 901, 4}, +{5, 45, 17, 2, 14, 46, 48, 38, 181, 50, 155, 3, 186, 54, 61, 29, 21, 227, 281, 80, 540, 106, 12, 400, 52, 1, 58, 32, 328, 171, 209, 487}, +{16, 18, 265, 121, 158, 35, 60, 9, 39, 7, 329, 105, 252, 68, 24, 1, 132, 167, 159, 22, 0, 49, 286, 101, 21, 146, 23, 327, 120, 709, 5, 14}, +{108, 467, 283, 56, 389, 650, 123, 412, 33, 177, 899, 475, 216, 453, 269, 349, 619, 65, 51, 730, 403, 670, 23, 196, 523, 128, 84, 13, 401, 789, 503, 543}, +{514, 3, 11, 377, 328, 4, 361, 507, 57, 403, 14, 880, 130, 485, 176, 215, 236, 38, 152, 102, 211, 56, 62, 757, 54, 585, 300, 556, 34, 555, 40, 229}, +{3, 555, 62, 266, 130, 99, 507, 139, 514, 12, 152, 229, 215, 305, 57, 40, 440, 33, 403, 471, 38, 56, 475, 14, 361, 313, 775, 328, 196, 548, 123, 23}, +{120, 202, 318, 15, 77, 13, 1, 450, 33, 269, 515, 260, 5, 128, 494, 51, 23, 700, 102, 141, 40, 753, 326, 403, 817, 137, 523, 21, 177, 922, 342, 7}, +{15, 1, 515, 23, 0, 13, 700, 2, 51, 753, 180, 5, 165, 21, 197, 12, 3, 120, 115, 4, 141, 6, 9, 7, 457, 33, 386, 202, 82, 8, 31, 341}, +{15, 180, 515, 82, 351, 700, 10, 317, 753, 115, 217, 365, 141, 898, 33, 901, 13, 23, 110, 854, 752, 77, 1, 197, 4, 341, 143, 36, 64, 352, 102, 9}, +{104, 289, 66, 707, 214, 90, 712, 64, 97, 173, 20, 0, 414, 194, 874, 43, 32, 7, 568, 560, 65, 38, 426, 312, 715, 192, 376, 74, 835, 5, 324, 147}, +{84, 56, 0, 554, 63, 65, 453, 249, 123, 643, 18, 26, 847, 475, 511, 403, 416, 561, 524, 289, 370, 73, 9, 19, 45, 42, 719, 194, 27, 467, 33, 730}, +{21, 346, 13, 350, 308, 826, 197, 101, 352, 68, 570, 0, 165, 23, 9, 841, 115, 100, 509, 694, 221, 230, 35, 217, 569, 88, 124, 749, 1, 777, 212, 154}, +{16, 92, 7, 24, 60, 18, 35, 140, 126, 14, 50, 71, 46, 330, 2, 75, 246, 5, 121, 267, 571, 1, 230, 309, 220, 0, 9, 64, 146, 236, 54, 108}, +{82, 15, 515, 898, 365, 700, 180, 33, 341, 753, 77, 901, 10, 115, 55, 351, 21, 5, 1, 4, 13, 102, 36, 217, 2, 165, 752, 120, 197, 117, 11, 317}, +{16, 24, 35, 18, 69, 71, 140, 1, 103, 7, 189, 68, 0, 50, 9, 108, 2, 133, 60, 267, 230, 46, 149, 67, 167, 118, 92, 14, 75, 21, 191, 38}, +{60, 71, 16, 18, 7, 20, 43, 118, 35, 68, 375, 28, 608, 0, 175, 566, 154, 92, 14, 149, 628, 33, 22, 13, 2, 10, 279, 23, 107, 356, 55, 117}, +{187, 258, 871, 295, 201, 434, 219, 224, 489, 384, 268, 110, 261, 839, 44, 699, 93, 116, 36, 131, 141, 228, 144, 160, 940, 567, 244, 406, 137, 574, 98, 253}, +{66, 7, 97, 172, 192, 712, 232, 324, 204, 74, 43, 448, 387, 426, 568, 20, 526, 107, 104, 135, 356, 729, 173, 0, 22, 5, 32, 95, 2, 64, 500, 560}, +{15, 515, 700, 753, 1, 4, 0, 341, 13, 3, 134, 2, 5, 33, 11, 77, 12, 10, 23, 197, 365, 901, 7, 40, 217, 32, 21, 6, 51, 180, 961, 37}, +{0, 28, 24, 9, 35, 65, 16, 124, 68, 55, 109, 154, 7, 39, 22, 149, 158, 14, 175, 1, 49, 252, 18, 71, 2, 168, 289, 419, 108, 420, 67, 101}, +{7, 16, 14, 92, 2, 46, 140, 24, 220, 35, 38, 60, 75, 1, 50, 18, 87, 54, 5, 126, 29, 52, 278, 262, 314, 107, 71, 21, 172, 135, 330, 394}, +{7, 92, 16, 14, 172, 126, 2, 60, 140, 35, 135, 314, 278, 46, 24, 38, 232, 107, 330, 66, 5, 18, 150, 246, 230, 97, 52, 1, 121, 563, 279, 21}, +{6, 26, 235, 53, 297, 436, 27, 19, 25, 73, 113, 445, 90, 214, 65, 42, 64, 289, 250, 611, 624, 32, 45, 648, 614, 17, 85, 491, 34, 122, 200, 416}, +{352, 141, 1, 217, 854, 752, 351, 180, 244, 36, 110, 661, 82, 258, 816, 160, 295, 219, 567, 224, 230, 269, 922, 144, 260, 268, 93, 201, 137, 116, 489, 202}, +{16, 60, 35, 18, 126, 107, 68, 191, 92, 121, 7, 14, 598, 20, 493, 279, 167, 446, 118, 0, 28, 43, 463, 55, 24, 212, 375, 566, 9, 150, 575, 21}, +{15, 1, 515, 2, 4, 13, 0, 700, 3, 5, 23, 753, 341, 77, 51, 115, 33, 11, 180, 10, 197, 141, 6, 165, 7, 901, 102, 40, 9, 202, 217, 12}, +{23, 51, 13, 202, 21, 5, 1, 120, 15, 137, 128, 125, 32, 2, 12, 141, 33, 165, 64, 515, 403, 318, 700, 48, 180, 7, 6, 450, 115, 523, 475, 260}, +{131, 716, 224, 371, 219, 187, 737, 616, 385, 254, 9, 98, 105, 924, 31, 258, 836, 39, 127, 578, 49, 916, 44, 761, 272, 137, 944, 159, 0, 242, 442, 22}, +{15, 515, 700, 1, 753, 2, 5, 0, 4, 13, 3, 180, 11, 141, 197, 10, 341, 217, 33, 134, 165, 6, 77, 7, 317, 12, 352, 64, 365, 32, 102, 40}, +{66, 74, 7, 173, 174, 29, 192, 2, 222, 20, 226, 43, 353, 52, 712, 6, 0, 138, 500, 204, 97, 145, 64, 104, 426, 673, 355, 90, 25, 5, 65, 87}, +{5, 259, 786, 534, 590, 493, 279, 49, 13, 581, 465, 21, 929, 35, 941, 132, 147, 32, 23, 612, 362, 626, 107, 121, 178, 0, 146, 61, 48, 939, 10, 18}, +{2, 14, 16, 7, 278, 69, 135, 140, 46, 24, 267, 35, 92, 38, 1, 189, 29, 52, 309, 60, 66, 75, 71, 172, 74, 357, 18, 87, 67, 6, 230, 5}, +{165, 13, 308, 197, 391, 23, 401, 15, 51, 457, 180, 509, 115, 569, 3, 629, 961, 719, 34, 758, 317, 734, 14, 29, 46, 2, 17, 901, 38, 453, 5, 217}, +{1, 22, 2, 14, 0, 28, 7, 168, 67, 49, 65, 24, 36, 95, 5, 105, 55, 35, 12, 46, 69, 16, 114, 159, 194, 50, 10, 9, 158, 83, 164, 109}, +{34, 453, 3, 196, 130, 14, 322, 11, 47, 51, 377, 236, 361, 4, 730, 153, 514, 711, 57, 440, 62, 17, 161, 108, 176, 59, 485, 56, 162, 412, 202, 117}, +{18, 16, 21, 23, 48, 13, 24, 35, 121, 5, 156, 60, 51, 1, 7, 132, 141, 221, 163, 115, 0, 271, 447, 340, 363, 202, 125, 71, 2, 781, 22, 698}, +{165, 13, 457, 23, 197, 961, 629, 569, 341, 41, 12, 38, 401, 901, 54, 51, 115, 17, 15, 509, 421, 37, 62, 45, 719, 57, 32, 328, 117, 758, 157, 99}, +{2, 1, 77, 141, 33, 64, 3, 102, 0, 23, 13, 5, 128, 10, 6, 15, 180, 202, 269, 40, 51, 515, 7, 165, 137, 117, 318, 4, 700, 153, 197, 352}, +{68, 212, 0, 124, 101, 9, 154, 16, 562, 191, 21, 149, 65, 24, 35, 1, 118, 167, 818, 350, 520, 100, 722, 841, 264, 71, 13, 302, 478, 23, 375, 346}, +{98, 23, 48, 598, 13, 293, 541, 21, 125, 121, 51, 807, 0, 31, 35, 259, 126, 7, 386, 1, 223, 783, 10, 107, 199, 20, 221, 144, 342, 963, 49, 64}, +{21, 13, 5, 586, 1, 23, 167, 48, 33, 781, 647, 49, 165, 18, 51, 271, 77, 32, 761, 118, 0, 82, 391, 22, 146, 141, 459, 31, 197, 156, 115, 4}, +{2, 1, 5, 61, 29, 7, 58, 45, 14, 6, 425, 32, 70, 52, 290, 738, 207, 21, 72, 112, 66, 76, 655, 17, 186, 46, 64, 263, 38, 0, 128, 87}, +{39, 265, 9, 100, 1, 333, 363, 101, 18, 411, 447, 254, 166, 310, 31, 98, 264, 30, 639, 404, 156, 286, 16, 93, 593, 203, 272, 682, 0, 905, 44, 821}, +{6, 2, 1, 19, 29, 51, 26, 108, 25, 74, 5, 23, 14, 114, 13, 386, 133, 103, 42, 66, 453, 70, 309, 138, 719, 324, 65, 38, 64, 96, 52, 75}, +{20, 43, 356, 107, 49, 858, 595, 7, 414, 359, 0, 5, 392, 319, 97, 612, 422, 819, 14, 376, 173, 246, 22, 470, 147, 427, 230, 92, 197, 33, 683, 95}, +{0, 9, 68, 35, 65, 67, 114, 101, 28, 1, 124, 175, 336, 69, 154, 103, 83, 24, 189, 133, 39, 16, 50, 7, 2, 149, 55, 251, 18, 345, 230, 36}, +{23, 13, 51, 15, 0, 1, 515, 115, 165, 2, 5, 12, 700, 202, 4, 21, 141, 457, 753, 197, 10, 3, 180, 120, 32, 9, 318, 11, 453, 64, 6, 269}, +{121, 195, 60, 16, 126, 107, 98, 271, 146, 407, 132, 35, 1, 167, 199, 223, 493, 191, 279, 20, 18, 5, 43, 7, 21, 92, 48, 393, 0, 362, 212, 467}, +{31, 44, 299, 116, 393, 144, 492, 456, 268, 22, 105, 0, 367, 918, 384, 434, 127, 489, 98, 9, 963, 125, 242, 948, 1, 28, 206, 49, 36, 51, 93, 293}, +{23, 13, 457, 51, 165, 401, 719, 758, 197, 453, 961, 629, 308, 14, 15, 12, 730, 3, 386, 569, 391, 29, 739, 515, 34, 828, 832, 901, 115, 514, 670, 341}, +{105, 36, 131, 22, 180, 115, 341, 127, 169, 1, 9, 31, 64, 98, 44, 365, 317, 141, 272, 143, 160, 55, 219, 86, 197, 776, 239, 187, 0, 535, 13, 752}, +{1, 6, 2, 14, 66, 25, 29, 5, 108, 67, 65, 114, 19, 38, 26, 52, 74, 7, 24, 18, 69, 86, 36, 388, 64, 51, 17, 83, 23, 46, 42, 75}, +{51, 386, 23, 453, 719, 13, 730, 6, 457, 670, 758, 19, 401, 165, 2, 475, 47, 26, 899, 14, 108, 17, 1, 5, 197, 29, 894, 754, 236, 74, 27, 285}, +{252, 18, 9, 101, 121, 16, 132, 0, 419, 167, 364, 60, 604, 35, 265, 363, 146, 271, 39, 158, 68, 109, 28, 329, 848, 24, 647, 907, 682, 159, 212, 55}, +{283, 503, 128, 432, 26, 193, 63, 269, 789, 529, 102, 122, 389, 275, 678, 6, 25, 318, 445, 4, 342, 27, 573, 605, 177, 862, 643, 291, 216, 57, 235, 59}, +{2, 1, 29, 75, 69, 52, 14, 6, 46, 74, 87, 7, 220, 226, 278, 38, 135, 66, 267, 70, 16, 262, 25, 24, 380, 324, 357, 140, 67, 394, 97, 222}, +{97, 298, 69, 7, 66, 140, 189, 24, 16, 267, 172, 423, 60, 150, 14, 314, 92, 71, 81, 501, 43, 35, 74, 6, 517, 232, 149, 607, 83, 330, 18, 2}, +{475, 421, 403, 899, 51, 805, 523, 958, 453, 817, 23, 615, 401, 801, 120, 326, 202, 670, 494, 730, 450, 386, 115, 629, 260, 576, 77, 365, 569, 0, 165, 13}, +{7, 20, 14, 128, 77, 97, 112, 202, 2, 177, 16, 415, 269, 318, 275, 66, 107, 43, 141, 414, 135, 38, 307, 10, 58, 0, 6, 291, 32, 5, 4, 40}, +{24, 14, 7, 0, 2, 1, 22, 28, 16, 65, 168, 124, 35, 67, 108, 109, 18, 49, 10, 149, 69, 158, 5, 95, 289, 12, 55, 6, 36, 71, 46, 21}, +{26, 80, 27, 73, 122, 25, 19, 17, 6, 42, 684, 209, 445, 573, 667, 106, 45, 690, 4, 611, 255, 680, 297, 495, 65, 59, 128, 119, 483, 113, 64, 53}, +{107, 259, 362, 376, 465, 20, 470, 147, 595, 534, 612, 683, 660, 43, 5, 49, 581, 0, 858, 35, 427, 246, 97, 786, 178, 356, 14, 21, 142, 878, 7, 279}, +{131, 30, 228, 190, 856, 406, 224, 88, 219, 530, 863, 613, 778, 274, 944, 816, 187, 39, 100, 160, 258, 31, 44, 93, 1, 321, 539, 36, 871, 137, 435, 531}, +{113, 6, 311, 25, 45, 491, 80, 611, 27, 26, 209, 667, 17, 73, 122, 42, 684, 396, 19, 85, 106, 5, 614, 4, 2, 255, 151, 29, 1, 64, 648, 61}, +{15, 515, 700, 753, 0, 1, 23, 51, 120, 2, 13, 82, 5, 260, 9, 4, 341, 77, 180, 115, 141, 10, 7, 12, 450, 8, 202, 901, 197, 351, 165, 93}, +{219, 127, 98, 258, 395, 421, 924, 293, 242, 201, 697, 105, 276, 51, 308, 23, 453, 272, 401, 944, 512, 137, 13, 31, 284, 567, 386, 365, 116, 131, 964, 125}, +{15, 180, 352, 141, 515, 752, 217, 82, 1, 317, 854, 700, 351, 753, 115, 341, 110, 13, 260, 120, 21, 36, 33, 898, 23, 10, 5, 365, 4, 160, 901, 137}, +{129, 123, 17, 257, 162, 184, 205, 249, 183, 769, 5, 80, 3, 4, 229, 130, 119, 45, 90, 99, 618, 106, 57, 497, 12, 128, 2, 84, 59, 152, 27, 40}, +{33, 102, 23, 77, 64, 128, 51, 13, 0, 202, 10, 141, 40, 15, 1, 22, 117, 137, 2, 86, 4, 403, 269, 153, 515, 196, 65, 11, 700, 115, 99, 5}, +{7, 14, 2, 16, 172, 107, 46, 92, 5, 135, 35, 202, 294, 87, 38, 232, 29, 97, 20, 21, 24, 1, 60, 220, 66, 43, 12, 0, 126, 52, 54, 70}, +{403, 576, 615, 523, 475, 326, 805, 817, 494, 421, 51, 202, 120, 450, 137, 453, 23, 859, 260, 401, 402, 77, 33, 670, 0, 958, 15, 197, 386, 515, 165, 480}, +{141, 352, 217, 137, 0, 180, 202, 349, 9, 269, 23, 51, 115, 291, 77, 372, 13, 317, 120, 752, 365, 351, 93, 22, 2, 341, 64, 10, 82, 854, 28, 18}, +{1, 23, 13, 51, 202, 141, 5, 165, 21, 15, 120, 180, 64, 2, 197, 125, 33, 102, 12, 7, 137, 515, 48, 128, 269, 318, 93, 700, 0, 403, 9, 4}, +{25, 151, 6, 145, 122, 29, 174, 45, 113, 74, 4, 665, 42, 138, 2, 614, 416, 287, 19, 348, 746, 0, 66, 26, 1, 7, 64, 243, 311, 396, 81, 624}, +{30, 190, 254, 166, 100, 382, 731, 829, 88, 131, 264, 795, 9, 93, 625, 274, 438, 1, 578, 613, 716, 31, 44, 39, 530, 36, 616, 921, 265, 203, 160, 77}, +{132, 5, 21, 13, 1, 23, 32, 195, 379, 687, 156, 121, 626, 296, 48, 70, 850, 146, 51, 82, 883, 771, 35, 49, 652, 407, 60, 4, 260, 0, 845, 33}, +{9, 254, 0, 49, 272, 131, 39, 159, 688, 101, 105, 578, 518, 158, 286, 28, 327, 333, 68, 224, 252, 219, 344, 16, 22, 1, 716, 31, 30, 228, 24, 890}, +{16, 7, 35, 60, 18, 20, 14, 68, 9, 0, 28, 118, 43, 92, 126, 55, 107, 2, 101, 154, 24, 71, 5, 202, 121, 109, 22, 252, 21, 97, 1, 621}, +{15, 515, 700, 753, 13, 1, 341, 2, 0, 4, 3, 5, 11, 23, 10, 33, 117, 12, 901, 197, 6, 134, 77, 8, 165, 317, 21, 365, 217, 7, 17, 40}, +{78, 19, 444, 47, 26, 390, 27, 453, 130, 813, 108, 730, 711, 65, 412, 122, 51, 680, 113, 235, 690, 196, 630, 283, 128, 236, 14, 64, 73, 53, 200, 445}, +{2, 7, 29, 5, 61, 6, 45, 1, 66, 113, 112, 14, 52, 315, 738, 128, 32, 151, 74, 16, 20, 64, 70, 21, 592, 0, 25, 4, 425, 43, 491, 222}, +{145, 112, 74, 66, 6, 29, 26, 70, 19, 396, 25, 87, 2, 287, 135, 151, 138, 222, 5, 226, 42, 122, 7, 307, 1, 644, 45, 58, 113, 651, 635, 632}, +{92, 16, 7, 60, 126, 24, 140, 35, 14, 232, 18, 121, 246, 71, 46, 267, 172, 150, 107, 314, 132, 146, 230, 2, 278, 108, 330, 199, 236, 5, 38, 572}, +{13, 115, 197, 538, 569, 341, 98, 55, 165, 127, 365, 762, 219, 286, 844, 23, 170, 206, 734, 638, 535, 901, 169, 253, 629, 0, 873, 509, 180, 10, 332, 258}, +{58, 151, 74, 53, 287, 27, 29, 396, 6, 70, 2, 73, 5, 52, 112, 26, 651, 1, 297, 113, 17, 75, 19, 45, 334, 445, 145, 34, 315, 549, 436, 331}, +{214, 289, 90, 874, 104, 751, 64, 65, 312, 835, 204, 249, 750, 194, 74, 81, 875, 32, 519, 288, 348, 0, 174, 247, 636, 715, 138, 192, 784, 6, 524, 280}, +{9, 39, 28, 35, 30, 0, 166, 49, 1, 175, 439, 158, 64, 346, 36, 101, 67, 364, 86, 88, 274, 100, 168, 55, 23, 10, 420, 22, 190, 141, 505, 180}, +{341, 901, 15, 515, 700, 753, 1, 365, 10, 0, 569, 180, 2, 197, 115, 31, 165, 3, 5, 4, 44, 22, 317, 13, 9, 951, 23, 253, 116, 143, 762, 93}, +{120, 202, 77, 450, 260, 15, 128, 318, 102, 515, 494, 13, 817, 700, 269, 5, 403, 51, 1, 33, 23, 753, 82, 326, 141, 342, 291, 137, 21, 523, 351, 32}, +{13, 115, 241, 64, 180, 32, 125, 197, 165, 4, 118, 22, 21, 23, 16, 247, 237, 28, 225, 191, 95, 141, 167, 5, 0, 341, 288, 35, 459, 18, 177, 24}, +{16, 24, 35, 14, 1, 2, 7, 69, 18, 46, 60, 50, 267, 140, 71, 189, 108, 38, 75, 92, 0, 5, 9, 230, 67, 21, 309, 335, 54, 236, 394, 220}, +{15, 515, 700, 753, 898, 180, 901, 341, 197, 638, 10, 165, 33, 1, 115, 4, 77, 365, 317, 13, 102, 217, 117, 0, 5, 2, 253, 3, 82, 569, 21, 752}, +{193, 523, 18, 84, 56, 730, 233, 65, 4, 817, 90, 33, 643, 403, 91, 511, 453, 240, 59, 11, 214, 51, 719, 196, 153, 475, 32, 123, 64, 847, 102, 561}, +{112, 29, 151, 2, 74, 6, 66, 7, 222, 145, 287, 45, 5, 624, 52, 25, 113, 416, 58, 122, 19, 70, 186, 204, 4, 87, 644, 549, 337, 884, 32, 0}, +{13, 0, 23, 2, 1, 15, 33, 3, 77, 515, 141, 5, 4, 217, 10, 51, 64, 180, 700, 115, 6, 117, 11, 7, 753, 40, 102, 165, 197, 22, 317, 153}, +{28, 0, 1, 67, 65, 9, 2, 114, 83, 69, 103, 50, 36, 22, 55, 24, 46, 14, 124, 109, 35, 7, 16, 38, 133, 160, 389, 323, 18, 12, 154, 5}, +{121, 132, 18, 167, 271, 146, 101, 363, 621, 9, 411, 647, 16, 354, 520, 60, 212, 932, 1, 806, 55, 0, 195, 446, 68, 35, 31, 364, 777, 252, 407, 118}, +{26, 6, 85, 396, 122, 624, 25, 19, 42, 445, 64, 648, 573, 416, 174, 680, 665, 214, 45, 348, 90, 65, 194, 145, 113, 881, 138, 289, 112, 436, 297, 544}, +{16, 146, 18, 92, 24, 199, 60, 71, 121, 126, 35, 108, 156, 953, 271, 674, 132, 7, 32, 640, 360, 246, 649, 118, 21, 95, 5, 517, 14, 9, 1, 314}, +{51, 13, 23, 453, 475, 730, 719, 15, 457, 403, 64, 115, 33, 95, 4, 523, 3, 12, 21, 6, 899, 102, 5, 128, 401, 202, 11, 141, 308, 515, 22, 125}, +{151, 396, 6, 53, 27, 113, 58, 26, 73, 112, 74, 287, 45, 29, 297, 19, 145, 70, 138, 445, 315, 436, 34, 2, 17, 573, 5, 61, 549, 491, 1, 80}, +{223, 1, 888, 774, 260, 98, 269, 385, 349, 202, 96, 141, 421, 622, 730, 863, 318, 697, 87, 453, 393, 418, 922, 834, 751, 5, 163, 335, 120, 291, 352, 30}, +{16, 60, 92, 35, 126, 121, 7, 150, 246, 18, 107, 1, 598, 24, 167, 195, 14, 97, 71, 279, 98, 441, 191, 199, 517, 146, 356, 223, 298, 271, 230, 0}, +{22, 1, 105, 28, 239, 170, 0, 55, 95, 31, 36, 301, 2, 320, 98, 127, 9, 49, 44, 64, 35, 67, 10, 86, 5, 12, 109, 23, 168, 13, 21, 312}, +{2, 6, 5, 207, 292, 76, 1, 119, 45, 32, 17, 29, 61, 306, 790, 58, 240, 106, 14, 64, 214, 151, 476, 710, 7, 72, 84, 128, 4, 179, 70, 25}, +{51, 23, 221, 254, 115, 13, 438, 530, 125, 48, 21, 39, 541, 960, 386, 49, 1, 613, 15, 840, 228, 308, 627, 131, 688, 401, 5, 326, 421, 158, 165, 83}, +{1, 5, 2, 0, 12, 22, 21, 36, 10, 14, 48, 86, 23, 13, 32, 54, 3, 4, 28, 65, 51, 50, 137, 37, 208, 114, 9, 38, 17, 7, 281, 202}, +{363, 23, 447, 182, 296, 340, 1, 93, 698, 478, 379, 156, 284, 144, 18, 269, 21, 98, 141, 70, 668, 411, 664, 658, 110, 914, 67, 937, 180, 691, 335, 291}, +{17, 32, 45, 498, 41, 115, 180, 197, 106, 62, 54, 38, 546, 165, 13, 155, 468, 509, 341, 243, 241, 217, 542, 15, 57, 536, 428, 51, 117, 721, 292, 129}, +{32, 95, 64, 246, 22, 92, 180, 13, 5, 652, 125, 241, 638, 237, 7, 49, 4, 126, 21, 115, 197, 296, 888, 316, 0, 165, 774, 23, 16, 392, 1, 534}, +{15, 515, 700, 753, 33, 341, 13, 217, 4, 141, 77, 23, 180, 317, 1, 10, 102, 351, 82, 115, 40, 5, 854, 21, 137, 11, 352, 901, 365, 117, 197, 0}, +{15, 120, 1, 82, 93, 217, 515, 260, 77, 141, 13, 110, 700, 351, 352, 23, 180, 753, 21, 854, 202, 317, 64, 349, 269, 51, 165, 137, 5, 128, 291, 36}, +{13, 23, 51, 141, 77, 0, 33, 4, 115, 64, 2, 10, 102, 202, 217, 128, 1, 177, 269, 11, 7, 22, 6, 21, 32, 9, 180, 40, 15, 3, 165, 318}, +{478, 264, 1, 520, 98, 724, 9, 682, 223, 664, 21, 759, 13, 772, 604, 100, 23, 363, 411, 48, 821, 5, 0, 905, 909, 447, 31, 265, 88, 101, 166, 39}, +{20, 29, 7, 2, 77, 416, 6, 128, 33, 5, 0, 113, 104, 32, 43, 13, 491, 66, 23, 21, 102, 51, 74, 210, 202, 525, 64, 318, 10, 81, 174, 14}, +{2, 1, 5, 14, 7, 58, 61, 29, 45, 290, 46, 38, 52, 21, 32, 270, 6, 592, 425, 0, 75, 155, 16, 48, 17, 50, 72, 70, 207, 24, 263, 663}, +{80, 6, 17, 209, 106, 26, 483, 113, 19, 469, 255, 25, 378, 27, 495, 833, 45, 64, 161, 2, 61, 667, 76, 742, 32, 90, 445, 5, 814, 65, 887, 119}, +{98, 223, 393, 1, 354, 834, 195, 791, 447, 697, 284, 293, 360, 541, 781, 156, 51, 807, 18, 664, 421, 411, 163, 668, 48, 31, 591, 765, 883, 386, 948, 23}, +{679, 141, 816, 36, 93, 406, 876, 144, 228, 137, 1, 180, 669, 21, 332, 251, 5, 269, 116, 187, 96, 351, 202, 752, 317, 64, 203, 831, 574, 466, 855, 345}, +{15, 515, 700, 13, 1, 753, 2, 0, 23, 341, 3, 5, 4, 10, 51, 11, 33, 165, 6, 7, 115, 197, 12, 64, 180, 153, 217, 77, 9, 569, 901, 317}, +{13, 23, 202, 51, 5, 21, 403, 15, 120, 64, 1, 450, 128, 141, 12, 523, 33, 165, 494, 125, 2, 515, 269, 7, 48, 102, 318, 95, 260, 180, 453, 197}, +{16, 18, 24, 60, 71, 92, 146, 246, 199, 35, 140, 7, 9, 118, 121, 108, 167, 230, 126, 132, 0, 640, 156, 14, 68, 133, 267, 360, 649, 271, 64, 55}, +{269, 141, 678, 177, 202, 77, 128, 318, 33, 947, 40, 120, 291, 349, 102, 137, 64, 352, 210, 864, 461, 498, 13, 342, 196, 23, 275, 450, 954, 0, 205, 111}, +{16, 24, 92, 18, 71, 60, 35, 7, 108, 191, 167, 246, 140, 14, 126, 21, 1, 68, 150, 118, 149, 388, 399, 9, 273, 0, 121, 796, 230, 48, 212, 517}, +{2, 14, 1, 29, 46, 75, 52, 70, 69, 171, 38, 7, 58, 163, 16, 5, 24, 220, 67, 112, 223, 54, 50, 409, 155, 35, 267, 186, 151, 334, 394, 140}, +{9, 252, 100, 265, 166, 39, 88, 404, 329, 0, 1, 520, 382, 812, 101, 593, 264, 274, 604, 676, 30, 118, 68, 553, 18, 664, 363, 23, 639, 865, 21, 411}, +{16, 18, 35, 24, 0, 60, 158, 7, 22, 68, 14, 49, 109, 159, 55, 9, 28, 71, 2, 10, 5, 105, 1, 118, 329, 13, 344, 23, 92, 20, 21, 126}, +{15, 13, 515, 700, 23, 0, 753, 1, 51, 2, 4, 10, 77, 5, 3, 197, 115, 165, 961, 202, 9, 457, 180, 12, 141, 22, 33, 120, 6, 11, 318, 31}, +{160, 93, 251, 137, 317, 1, 180, 36, 120, 217, 345, 752, 617, 352, 332, 10, 96, 531, 498, 318, 365, 202, 141, 269, 816, 341, 901, 679, 143, 35, 83, 968}, +{6, 25, 42, 128, 19, 59, 122, 4, 85, 26, 611, 27, 269, 233, 45, 0, 343, 91, 318, 80, 11, 177, 283, 73, 33, 614, 2, 77, 64, 138, 445, 216}, +{95, 64, 74, 7, 32, 81, 51, 204, 0, 20, 237, 65, 56, 38, 91, 23, 207, 180, 347, 343, 29, 6, 511, 52, 49, 10, 25, 18, 554, 370, 14, 312}, +{202, 120, 326, 260, 450, 817, 494, 318, 137, 403, 128, 77, 523, 553, 859, 5, 704, 1, 15, 23, 13, 576, 7, 16, 615, 51, 682, 291, 515, 0, 21, 234}, +{20, 43, 107, 356, 362, 126, 595, 92, 359, 7, 422, 319, 493, 16, 858, 5, 392, 246, 414, 683, 60, 0, 35, 945, 441, 21, 259, 819, 49, 97, 279, 173}, +{25, 42, 6, 77, 33, 102, 0, 122, 4, 690, 29, 483, 210, 27, 21, 19, 2, 300, 18, 648, 680, 119, 117, 59, 1, 10, 342, 12, 26, 153, 91, 684}, +{31, 44, 299, 116, 125, 242, 456, 599, 22, 393, 0, 144, 492, 28, 268, 1, 9, 963, 301, 105, 367, 36, 127, 170, 384, 434, 206, 98, 918, 10, 13, 93}, +{410, 521, 686, 367, 662, 88, 335, 321, 201, 96, 98, 772, 144, 1, 934, 921, 443, 435, 284, 274, 264, 551, 120, 897, 44, 100, 33, 225, 744, 418, 909, 960}, +{142, 178, 878, 234, 132, 786, 195, 202, 77, 416, 147, 929, 146, 522, 167, 259, 687, 639, 450, 271, 626, 481, 590, 5, 198, 212, 771, 49, 0, 465, 315, 427}, +{254, 39, 131, 9, 272, 0, 578, 716, 310, 224, 30, 49, 105, 827, 518, 829, 166, 333, 616, 228, 613, 846, 101, 219, 1, 31, 890, 98, 159, 938, 252, 100}, +{230, 699, 854, 473, 450, 351, 831, 137, 855, 217, 352, 704, 800, 202, 251, 498, 160, 144, 206, 203, 317, 201, 253, 752, 418, 141, 1, 332, 82, 180, 443, 36}, +{403, 202, 475, 453, 494, 23, 51, 77, 318, 402, 13, 33, 128, 102, 137, 141, 120, 342, 269, 0, 450, 4, 899, 576, 40, 421, 275, 117, 217, 177, 196, 64}, +{23, 44, 98, 182, 291, 144, 116, 39, 110, 141, 96, 82, 905, 70, 367, 264, 125, 93, 77, 411, 120, 1, 658, 202, 100, 415, 107, 363, 197, 30, 447, 105}, +{15, 515, 1, 13, 700, 23, 77, 120, 0, 753, 51, 180, 202, 141, 260, 5, 21, 115, 2, 137, 128, 9, 450, 197, 365, 269, 12, 326, 110, 102, 318, 7}, +{0, 32, 18, 95, 207, 577, 193, 29, 61, 104, 64, 784, 715, 102, 693, 887, 81, 91, 583, 671, 403, 5, 52, 474, 397, 180, 138, 49, 37, 344, 38, 263}, +{0, 101, 9, 68, 252, 16, 100, 39, 166, 364, 124, 24, 154, 265, 212, 88, 18, 35, 329, 419, 28, 118, 71, 30, 65, 158, 191, 55, 1, 694, 21, 676}, +{16, 24, 191, 18, 35, 71, 167, 118, 149, 68, 212, 9, 0, 1, 21, 108, 101, 92, 60, 375, 302, 7, 589, 755, 124, 674, 350, 48, 562, 246, 13, 363}, +{2, 14, 69, 24, 1, 67, 46, 16, 38, 103, 29, 267, 7, 35, 189, 135, 278, 71, 108, 18, 83, 309, 52, 6, 149, 388, 75, 236, 60, 0, 150, 66}, +{13, 1, 23, 0, 4, 2, 51, 15, 180, 33, 3, 115, 5, 515, 141, 10, 77, 700, 11, 9, 197, 341, 202, 165, 217, 102, 22, 7, 753, 317, 365, 6}, +{447, 1, 698, 411, 31, 363, 98, 5, 919, 4, 156, 125, 759, 691, 13, 64, 459, 354, 44, 21, 48, 293, 30, 914, 478, 225, 82, 120, 2, 922, 848, 839}, +{854, 82, 351, 217, 141, 180, 352, 15, 515, 752, 1, 700, 317, 898, 753, 244, 10, 21, 922, 115, 77, 36, 4, 260, 64, 110, 372, 13, 5, 365, 120, 11}, +{0, 1, 4, 13, 5, 2, 82, 33, 3, 120, 10, 23, 9, 11, 77, 260, 21, 102, 8, 31, 40, 6, 351, 51, 64, 450, 22, 117, 93, 110, 7, 457}, +{51, 13, 403, 23, 12, 475, 1, 2, 21, 5, 453, 523, 115, 202, 817, 7, 0, 99, 3, 6, 450, 120, 494, 64, 22, 95, 49, 899, 10, 37, 32, 141}, +{180, 752, 352, 141, 498, 864, 317, 217, 9, 0, 115, 237, 230, 39, 30, 197, 83, 1, 930, 64, 35, 365, 372, 13, 579, 88, 702, 36, 101, 901, 482, 21}, +{16, 24, 0, 7, 22, 18, 28, 35, 14, 158, 71, 2, 109, 60, 1, 168, 49, 154, 124, 68, 10, 55, 92, 118, 159, 9, 5, 747, 95, 105, 65, 6}, +{15, 515, 700, 753, 0, 23, 1, 13, 341, 51, 120, 77, 141, 4, 137, 33, 260, 82, 202, 9, 180, 5, 351, 2, 291, 10, 11, 901, 21, 115, 40, 128}, +{24, 68, 35, 149, 18, 16, 0, 7, 9, 14, 189, 108, 69, 65, 67, 1, 71, 2, 118, 28, 140, 101, 114, 336, 230, 124, 175, 133, 46, 55, 251, 154}, +{13, 308, 197, 115, 125, 9, 165, 237, 391, 23, 509, 569, 546, 28, 49, 629, 22, 338, 317, 254, 749, 180, 468, 159, 903, 386, 217, 352, 558, 39, 36, 734}, +{64, 90, 32, 217, 77, 4, 141, 216, 172, 312, 128, 13, 86, 33, 597, 147, 352, 95, 5, 115, 875, 22, 59, 11, 102, 14, 182, 437, 97, 177, 874, 707}, +{1, 22, 36, 0, 105, 28, 2, 67, 95, 49, 55, 5, 239, 12, 86, 9, 83, 170, 312, 64, 31, 21, 23, 10, 164, 50, 114, 159, 208, 13, 7, 320}, +{9, 18, 16, 0, 159, 105, 101, 252, 49, 310, 24, 68, 35, 39, 265, 272, 7, 1, 60, 28, 455, 890, 329, 557, 118, 286, 55, 137, 327, 167, 5, 13}, +{129, 123, 214, 249, 618, 17, 5, 257, 205, 184, 460, 76, 2, 162, 769, 245, 90, 106, 128, 45, 119, 1, 183, 4, 3, 12, 179, 64, 6, 229, 99, 209}, +{51, 453, 719, 457, 23, 13, 730, 899, 475, 386, 4, 15, 11, 12, 670, 196, 515, 523, 961, 401, 153, 3, 700, 99, 753, 117, 403, 32, 120, 165, 57, 0}, +{173, 66, 192, 204, 20, 74, 104, 636, 7, 43, 289, 426, 825, 712, 560, 214, 81, 750, 65, 97, 707, 0, 90, 414, 64, 348, 32, 500, 22, 861, 95, 6}, +{13, 23, 1, 51, 5, 21, 141, 120, 202, 15, 165, 2, 515, 180, 12, 125, 0, 64, 82, 700, 197, 269, 32, 48, 260, 128, 115, 93, 9, 137, 33, 753}, +{200, 34, 322, 78, 472, 390, 27, 714, 19, 14, 136, 161, 453, 176, 236, 444, 59, 3, 62, 128, 108, 57, 283, 862, 73, 53, 47, 17, 412, 813, 4, 56}, +{33, 347, 66, 204, 426, 498, 56, 172, 97, 95, 5, 681, 546, 22, 10, 0, 135, 180, 4, 241, 19, 174, 6, 353, 263, 21, 7, 370, 42, 197, 27, 808}, +{131, 224, 219, 187, 385, 371, 258, 442, 254, 737, 31, 98, 836, 127, 924, 944, 44, 871, 908, 716, 39, 827, 201, 574, 116, 137, 36, 1, 276, 242, 578, 616}, +{1, 15, 2, 180, 4, 141, 13, 515, 0, 5, 3, 115, 700, 901, 341, 23, 217, 352, 753, 51, 197, 77, 317, 33, 365, 752, 165, 21, 6, 7, 269, 93}, +{370, 91, 718, 74, 81, 510, 397, 66, 636, 240, 355, 84, 138, 511, 18, 278, 6, 681, 701, 289, 90, 5, 214, 582, 64, 104, 0, 643, 192, 65, 750, 32}, +{15, 515, 700, 753, 13, 120, 1, 0, 165, 2, 197, 23, 260, 180, 4, 82, 51, 386, 8, 5, 12, 10, 3, 141, 351, 341, 326, 9, 450, 7, 64, 6}, +{32, 2, 76, 5, 1, 292, 72, 45, 476, 214, 21, 241, 29, 14, 17, 48, 129, 90, 179, 460, 464, 123, 290, 148, 519, 205, 3, 263, 249, 38, 710, 89}, +{13, 165, 115, 17, 197, 569, 23, 509, 457, 45, 32, 41, 106, 180, 62, 38, 659, 734, 155, 536, 341, 629, 961, 873, 587, 54, 431, 37, 391, 99, 405, 428}, +{68, 24, 35, 16, 0, 101, 9, 124, 154, 71, 149, 65, 18, 175, 28, 118, 7, 55, 302, 108, 92, 14, 22, 346, 1, 39, 429, 252, 375, 364, 10, 67}, +{0, 9, 1, 68, 230, 65, 35, 69, 83, 23, 101, 13, 141, 67, 217, 352, 21, 39, 16, 88, 28, 124, 212, 100, 115, 154, 51, 64, 30, 36, 10, 317}, +{100, 265, 88, 909, 410, 382, 812, 593, 1, 213, 321, 30, 252, 230, 352, 264, 9, 166, 689, 39, 676, 98, 21, 466, 724, 639, 478, 217, 13, 48, 553, 101}, +{113, 61, 198, 904, 43, 0, 5, 37, 899, 325, 20, 59, 33, 523, 204, 725, 817, 389, 470, 329, 222, 40, 174, 58, 22, 453, 690, 848, 122, 104, 788, 105}, +{16, 24, 141, 18, 7, 0, 71, 140, 35, 269, 75, 352, 12, 9, 108, 217, 5, 330, 60, 64, 199, 70, 22, 13, 486, 246, 318, 133, 65, 50, 23, 498}, +{271, 167, 121, 60, 18, 191, 146, 199, 16, 1, 446, 132, 575, 212, 463, 354, 126, 35, 598, 566, 727, 98, 107, 21, 608, 955, 640, 407, 5, 24, 223, 68}, +{15, 515, 115, 217, 700, 13, 317, 753, 141, 180, 33, 23, 110, 120, 4, 341, 82, 10, 1, 260, 365, 36, 64, 854, 351, 21, 51, 352, 137, 77, 40, 0}, +{173, 7, 97, 356, 43, 107, 20, 387, 729, 104, 426, 232, 560, 595, 359, 392, 414, 707, 885, 81, 5, 0, 66, 858, 612, 49, 861, 14, 22, 32, 819, 230}, +{15, 515, 700, 753, 13, 23, 51, 82, 0, 33, 165, 120, 196, 4, 1, 2, 197, 453, 260, 351, 180, 12, 40, 8, 386, 110, 5, 326, 9, 141, 217, 457}, +{9, 100, 120, 30, 77, 795, 137, 82, 202, 39, 264, 827, 578, 127, 0, 166, 373, 318, 18, 326, 141, 260, 1, 450, 731, 31, 33, 395, 217, 291, 341, 254}, +{14, 2, 67, 1, 24, 69, 0, 28, 65, 7, 46, 18, 114, 108, 36, 83, 38, 398, 9, 16, 124, 133, 103, 154, 50, 55, 22, 267, 29, 160, 35, 547}, +{14, 7, 69, 24, 66, 16, 2, 267, 189, 67, 71, 150, 140, 97, 18, 60, 172, 35, 6, 1, 38, 149, 388, 92, 83, 135, 108, 74, 462, 380, 29, 36}, +{15, 515, 700, 753, 1, 13, 2, 0, 4, 341, 5, 3, 23, 365, 11, 117, 180, 10, 12, 33, 134, 115, 77, 197, 217, 165, 6, 7, 317, 102, 21, 9}, +{1, 22, 0, 12, 5, 2, 36, 28, 21, 10, 86, 13, 23, 49, 128, 9, 95, 51, 55, 96, 208, 141, 48, 202, 4, 137, 37, 64, 105, 3, 50, 7}, +{605, 630, 63, 123, 736, 650, 65, 108, 444, 368, 561, 389, 19, 25, 42, 619, 122, 194, 183, 27, 53, 33, 84, 26, 297, 813, 114, 73, 256, 235, 249, 216}, +{127, 39, 9, 0, 31, 371, 98, 254, 1, 385, 395, 44, 30, 836, 187, 131, 100, 116, 284, 578, 299, 166, 28, 21, 737, 16, 276, 272, 23, 49, 137, 935}, +{2, 61, 6, 29, 45, 151, 1, 655, 7, 207, 32, 5, 112, 425, 17, 76, 833, 4, 14, 64, 58, 106, 119, 25, 113, 128, 72, 52, 70, 21, 292, 790}, +{2, 5, 17, 14, 3, 29, 23, 27, 13, 401, 46, 6, 51, 58, 1, 453, 45, 53, 34, 52, 133, 19, 236, 26, 181, 114, 99, 366, 151, 108, 218, 38}, +{31, 22, 170, 1, 301, 44, 127, 98, 36, 28, 55, 105, 239, 0, 338, 116, 512, 299, 293, 125, 86, 10, 242, 395, 2, 13, 9, 64, 841, 23, 95, 685}, +{1, 21, 2, 14, 5, 32, 48, 50, 38, 270, 46, 76, 290, 72, 45, 54, 17, 0, 155, 221, 263, 207, 37, 281, 430, 3, 89, 12, 181, 408, 36, 67}, +{17, 106, 119, 378, 84, 240, 62, 80, 383, 136, 306, 3, 56, 790, 742, 5, 207, 504, 64, 440, 32, 128, 45, 2, 123, 209, 14, 4, 61, 57, 297, 667}, +{13, 15, 1, 515, 23, 2, 0, 700, 4, 115, 3, 51, 5, 10, 753, 180, 33, 341, 217, 11, 165, 317, 365, 197, 6, 77, 40, 64, 22, 9, 7, 117}, +{772, 335, 96, 744, 1, 367, 662, 686, 652, 897, 303, 264, 521, 31, 225, 410, 141, 520, 260, 116, 64, 44, 321, 98, 144, 88, 919, 966, 340, 269, 349, 284}, +{1, 0, 5, 28, 36, 2, 12, 22, 83, 67, 65, 50, 24, 14, 9, 96, 21, 218, 18, 114, 48, 281, 54, 10, 7, 160, 181, 103, 37, 23, 133, 99}, +{25, 6, 145, 42, 138, 81, 174, 348, 525, 544, 26, 74, 85, 280, 287, 648, 746, 91, 66, 0, 29, 396, 204, 64, 636, 90, 122, 194, 355, 104, 65, 233}, +{16, 24, 0, 18, 28, 158, 7, 35, 49, 22, 68, 159, 55, 1, 14, 109, 105, 2, 9, 71, 65, 154, 124, 95, 424, 344, 60, 239, 118, 577, 21, 10}, +{352, 854, 699, 230, 93, 689, 137, 144, 217, 160, 251, 36, 669, 202, 351, 120, 617, 855, 752, 203, 332, 82, 450, 180, 141, 748, 831, 30, 258, 201, 1, 816}, +{15, 13, 515, 700, 1, 2, 0, 753, 23, 5, 4, 3, 51, 33, 10, 115, 11, 317, 217, 77, 180, 341, 117, 165, 6, 134, 197, 153, 64, 9, 102, 7}, +{104, 20, 43, 173, 66, 319, 0, 77, 202, 7, 198, 5, 97, 580, 355, 74, 2, 204, 174, 52, 712, 234, 426, 155, 102, 192, 32, 4, 500, 337, 226, 904}, +{13, 23, 15, 51, 1, 515, 0, 2, 5, 700, 141, 4, 753, 165, 115, 12, 3, 21, 457, 10, 180, 269, 32, 6, 197, 202, 9, 7, 120, 11, 77, 33}, +{15, 515, 700, 753, 0, 1, 13, 2, 23, 115, 4, 317, 8, 3, 5, 51, 9, 341, 10, 217, 22, 365, 33, 457, 6, 180, 77, 901, 197, 120, 18, 7}, +{15, 515, 700, 753, 1, 0, 2, 3, 4, 13, 5, 141, 23, 16, 82, 217, 457, 10, 365, 180, 9, 317, 51, 21, 269, 898, 64, 202, 11, 12, 318, 341}, +{2, 5, 1, 14, 50, 38, 29, 17, 114, 46, 133, 3, 45, 21, 58, 171, 181, 36, 218, 12, 6, 52, 0, 48, 137, 65, 361, 23, 155, 4, 285, 51}, +{0, 68, 9, 65, 101, 124, 35, 212, 16, 149, 154, 100, 24, 1, 114, 336, 67, 589, 252, 39, 71, 189, 69, 562, 18, 13, 30, 398, 118, 88, 265, 264}, +{1, 2, 14, 22, 0, 7, 67, 65, 28, 36, 24, 46, 168, 5, 86, 69, 38, 16, 49, 12, 289, 10, 194, 50, 83, 114, 95, 6, 18, 23, 55, 158}, +{13, 23, 15, 51, 515, 0, 700, 4, 1, 753, 2, 10, 115, 961, 457, 12, 33, 11, 3, 5, 197, 9, 165, 77, 102, 403, 453, 40, 64, 22, 37, 59}, +{15, 515, 700, 753, 0, 1, 2, 13, 23, 5, 51, 901, 8, 9, 180, 3, 7, 82, 4, 120, 12, 10, 719, 341, 6, 31, 141, 457, 197, 22, 115, 93}, +{100, 252, 88, 101, 0, 265, 9, 724, 48, 1, 21, 352, 213, 676, 410, 382, 321, 230, 30, 329, 593, 909, 39, 812, 553, 217, 23, 689, 520, 264, 166, 419}, +{2, 5, 1, 58, 171, 14, 46, 50, 29, 52, 45, 38, 186, 155, 67, 54, 151, 281, 334, 61, 48, 96, 17, 181, 103, 400, 502, 227, 21, 223, 12, 69}, +{23, 120, 13, 1, 202, 141, 51, 21, 165, 128, 260, 15, 5, 269, 137, 64, 33, 180, 82, 318, 93, 197, 77, 326, 515, 125, 110, 700, 450, 2, 32, 48}, +{341, 197, 10, 901, 13, 15, 8, 638, 569, 515, 479, 23, 180, 873, 700, 165, 143, 642, 0, 961, 753, 951, 1, 115, 509, 499, 116, 12, 498, 242, 82, 206}, +{15, 1, 23, 13, 515, 21, 120, 51, 2, 141, 202, 700, 5, 180, 165, 0, 753, 197, 12, 7, 33, 260, 352, 137, 269, 4, 82, 128, 48, 9, 110, 6}, +{2, 29, 50, 58, 1, 6, 5, 52, 14, 262, 17, 46, 27, 53, 151, 34, 171, 74, 324, 26, 38, 309, 45, 113, 19, 96, 287, 396, 223, 67, 73, 583}, +{13, 23, 141, 51, 4, 202, 0, 115, 77, 2, 33, 217, 5, 317, 180, 64, 10, 269, 3, 9, 15, 21, 1, 128, 102, 137, 318, 11, 352, 515, 22, 31}, +{1, 67, 0, 24, 50, 5, 14, 18, 16, 69, 2, 9, 103, 35, 83, 12, 96, 28, 54, 7, 58, 223, 21, 46, 281, 48, 65, 181, 22, 38, 36, 108}, +{13, 23, 141, 51, 77, 64, 202, 115, 33, 102, 128, 4, 0, 269, 10, 21, 217, 32, 180, 318, 9, 137, 2, 11, 22, 291, 7, 177, 16, 31, 165, 197}, +{317, 115, 180, 365, 873, 498, 217, 341, 13, 752, 482, 197, 569, 352, 1, 901, 36, 23, 457, 468, 165, 346, 546, 143, 509, 134, 579, 876, 868, 2, 332, 21}, +{184, 257, 205, 229, 152, 17, 57, 497, 266, 432, 452, 524, 5, 619, 381, 32, 4, 90, 2, 12, 313, 128, 45, 59, 245, 106, 3, 471, 129, 769, 339, 214}, +{13, 23, 1, 0, 15, 2, 4, 515, 51, 3, 10, 33, 5, 700, 115, 180, 753, 77, 11, 365, 341, 217, 9, 6, 197, 7, 102, 165, 317, 40, 22, 64}, +{626, 70, 771, 687, 379, 846, 767, 761, 518, 878, 82, 481, 31, 786, 49, 591, 178, 163, 407, 44, 87, 13, 845, 125, 590, 371, 195, 120, 98, 557, 937, 351}, +{264, 1, 410, 909, 772, 897, 686, 521, 335, 478, 98, 96, 691, 639, 100, 44, 284, 382, 31, 321, 744, 88, 914, 724, 662, 765, 223, 9, 682, 363, 0, 367}, +{13, 23, 1, 2, 0, 15, 51, 515, 5, 10, 4, 33, 115, 77, 180, 700, 3, 141, 217, 40, 6, 753, 317, 197, 64, 165, 7, 11, 102, 9, 341, 22}, +{141, 77, 13, 64, 269, 23, 115, 21, 318, 217, 5, 202, 102, 33, 137, 2, 15, 291, 177, 51, 48, 180, 32, 4, 515, 352, 128, 7, 0, 10, 96, 11}, +{13, 15, 23, 515, 51, 0, 700, 753, 1, 2, 4, 10, 33, 11, 961, 453, 115, 40, 457, 14, 12, 3, 9, 5, 165, 401, 197, 77, 22, 21, 64, 102}, +{1, 22, 0, 36, 2, 31, 5, 12, 13, 105, 28, 9, 49, 86, 141, 21, 23, 95, 128, 55, 44, 115, 170, 10, 164, 98, 180, 4, 137, 239, 83, 51}, +{100, 101, 88, 0, 252, 9, 265, 30, 21, 39, 759, 724, 213, 329, 321, 13, 419, 68, 562, 382, 676, 352, 694, 35, 553, 410, 1, 166, 909, 593, 230, 23}, +{539, 88, 30, 190, 321, 530, 840, 144, 669, 435, 957, 748, 778, 100, 96, 418, 203, 213, 1, 131, 410, 228, 466, 274, 36, 382, 219, 863, 613, 83, 822, 352}, +{7, 97, 92, 173, 298, 107, 43, 314, 232, 140, 16, 356, 20, 387, 729, 362, 126, 359, 246, 14, 230, 501, 426, 441, 0, 5, 560, 66, 104, 779, 35, 60}, +{2, 14, 7, 1, 58, 5, 46, 16, 38, 70, 75, 45, 24, 155, 29, 0, 21, 52, 61, 163, 220, 50, 69, 270, 35, 48, 32, 171, 18, 6, 64, 54}, +{447, 411, 363, 664, 647, 98, 621, 1, 354, 271, 223, 478, 18, 777, 781, 936, 360, 759, 167, 132, 121, 48, 21, 156, 9, 195, 118, 293, 23, 691, 13, 264}, +{2, 1, 14, 65, 36, 67, 0, 7, 46, 22, 69, 5, 38, 24, 28, 6, 83, 29, 86, 114, 168, 50, 124, 208, 12, 18, 108, 10, 194, 484, 103, 16}, +{421, 386, 51, 791, 730, 958, 165, 801, 23, 453, 697, 403, 615, 13, 221, 523, 24, 899, 401, 326, 551, 670, 576, 102, 18, 33, 125, 77, 566, 115, 203, 197}, +{104, 319, 422, 945, 0, 81, 20, 43, 715, 32, 784, 693, 879, 7, 397, 74, 306, 207, 52, 681, 671, 2, 61, 173, 6, 636, 904, 95, 887, 5, 18, 192}, +{2, 29, 1, 46, 14, 52, 70, 262, 6, 26, 50, 67, 75, 96, 309, 38, 103, 112, 58, 19, 5, 163, 145, 83, 74, 220, 223, 357, 24, 69, 331, 25}, +{786, 929, 590, 771, 687, 626, 941, 178, 465, 259, 70, 5, 13, 21, 35, 534, 107, 518, 132, 49, 878, 48, 146, 121, 379, 279, 31, 767, 147, 195, 108, 125}, +{5, 2, 186, 45, 17, 29, 48, 50, 14, 61, 46, 155, 400, 1, 227, 171, 52, 58, 38, 54, 430, 209, 80, 281, 3, 106, 536, 311, 181, 243, 21, 502}, +{0, 32, 64, 95, 817, 494, 342, 403, 207, 202, 194, 389, 453, 365, 312, 180, 316, 5, 690, 237, 848, 577, 450, 61, 102, 523, 475, 289, 49, 241, 65, 482}, +{23, 13, 51, 15, 202, 515, 1, 0, 2, 12, 115, 4, 700, 5, 165, 753, 77, 457, 21, 141, 128, 10, 3, 64, 403, 32, 197, 318, 9, 11, 33, 117}, +{119, 2, 6, 76, 5, 17, 45, 292, 306, 240, 32, 1, 19, 84, 64, 61, 4, 209, 710, 80, 26, 0, 106, 27, 214, 25, 128, 129, 29, 179, 3, 113}, +{15, 515, 700, 1, 753, 0, 13, 23, 180, 120, 51, 2, 5, 33, 165, 197, 9, 450, 7, 260, 115, 523, 4, 12, 202, 141, 82, 77, 21, 102, 8, 6}, +{6, 138, 74, 280, 222, 85, 66, 226, 25, 42, 87, 204, 64, 337, 29, 135, 95, 174, 235, 26, 145, 65, 19, 32, 792, 294, 112, 52, 256, 2, 5, 22}, +{39, 9, 0, 101, 333, 158, 49, 252, 310, 254, 272, 68, 16, 18, 159, 286, 344, 455, 30, 109, 627, 327, 24, 105, 419, 100, 364, 22, 35, 1, 329, 709}, +{21, 5, 32, 14, 2, 1, 38, 72, 76, 54, 17, 3, 48, 221, 270, 0, 45, 46, 12, 181, 37, 89, 36, 50, 540, 290, 430, 10, 4, 741, 99, 23}, +{120, 137, 202, 269, 141, 260, 318, 450, 922, 494, 77, 291, 82, 15, 5, 351, 128, 1, 515, 326, 64, 854, 700, 352, 342, 21, 753, 678, 349, 32, 523, 90}, +{16, 24, 68, 35, 71, 18, 149, 118, 191, 167, 9, 0, 212, 124, 65, 246, 7, 67, 140, 189, 399, 101, 133, 60, 1, 108, 267, 114, 69, 92, 695, 154}, +{28, 0, 9, 67, 1, 22, 109, 36, 55, 65, 194, 114, 39, 83, 49, 69, 2, 35, 103, 50, 158, 208, 86, 420, 168, 289, 505, 24, 7, 185, 5, 323}, +{147, 325, 198, 427, 142, 178, 202, 798, 5, 376, 20, 318, 259, 43, 120, 450, 77, 234, 534, 904, 470, 465, 878, 725, 329, 14, 315, 0, 260, 858, 70, 61}, +{28, 0, 65, 9, 109, 1, 55, 67, 35, 22, 24, 39, 289, 7, 175, 14, 114, 2, 158, 124, 420, 194, 68, 16, 336, 36, 49, 69, 168, 570, 154, 505}, +{141, 180, 13, 115, 1, 23, 4, 269, 2, 202, 0, 317, 217, 51, 15, 5, 21, 352, 77, 318, 3, 752, 197, 10, 165, 365, 137, 341, 9, 515, 33, 64}, +{15, 515, 700, 0, 753, 1, 2, 13, 23, 9, 51, 5, 4, 901, 33, 7, 8, 3, 12, 93, 180, 120, 197, 6, 82, 341, 10, 141, 22, 260, 457, 115}, +{6, 74, 66, 1, 25, 75, 324, 380, 278, 26, 138, 85, 135, 500, 87, 42, 220, 841, 97, 350, 29, 19, 70, 226, 38, 21, 52, 606, 235, 889, 2, 14}, +{13, 23, 51, 12, 4, 15, 453, 0, 457, 1, 403, 165, 115, 3, 11, 2, 64, 5, 401, 10, 515, 37, 202, 33, 40, 32, 99, 475, 197, 700, 308, 17}, +{788, 180, 5, 83, 693, 319, 314, 4, 32, 21, 17, 11, 817, 3, 510, 498, 33, 12, 24, 104, 814, 120, 64, 117, 306, 804, 523, 450, 288, 160, 102, 43}, +{15, 1, 515, 13, 2, 700, 23, 0, 4, 753, 3, 341, 5, 51, 33, 11, 10, 6, 77, 7, 115, 102, 180, 165, 141, 9, 197, 217, 901, 40, 12, 64}, +{101, 18, 9, 167, 520, 16, 0, 118, 60, 212, 604, 364, 694, 24, 55, 252, 68, 917, 264, 35, 1, 121, 146, 363, 39, 100, 806, 5, 21, 166, 191, 28}, +{13, 23, 0, 33, 51, 141, 77, 4, 64, 2, 115, 217, 9, 102, 7, 202, 21, 10, 180, 3, 15, 128, 5, 269, 6, 32, 11, 16, 165, 352, 22, 317}, +{66, 135, 97, 74, 172, 6, 278, 7, 204, 324, 138, 174, 29, 85, 2, 87, 25, 140, 92, 192, 52, 38, 802, 69, 448, 500, 808, 620, 22, 1, 280, 232}, +{2, 24, 69, 6, 97, 7, 1, 0, 14, 298, 423, 66, 67, 29, 150, 25, 189, 267, 124, 74, 607, 18, 36, 81, 172, 33, 83, 38, 52, 273, 71, 809}, +{0, 9, 158, 39, 68, 49, 109, 16, 24, 333, 35, 344, 101, 22, 159, 254, 272, 30, 124, 65, 28, 18, 793, 154, 310, 252, 327, 105, 627, 419, 286, 55}, +{15, 515, 700, 10, 753, 33, 77, 180, 4, 341, 1, 197, 13, 115, 365, 23, 901, 317, 5, 102, 11, 217, 165, 117, 141, 40, 2, 3, 253, 21, 134, 55}, +{100, 166, 382, 478, 265, 264, 88, 39, 98, 1, 404, 274, 9, 593, 724, 921, 639, 438, 363, 682, 411, 31, 30, 812, 96, 447, 821, 905, 252, 0, 223, 435}, +{19, 283, 436, 53, 297, 26, 813, 432, 27, 128, 42, 25, 390, 503, 122, 736, 73, 123, 605, 63, 389, 529, 630, 250, 690, 65, 381, 444, 6, 269, 108, 216}, +{33, 202, 13, 128, 494, 0, 51, 141, 269, 1, 4, 2, 102, 180, 15, 137, 65, 95, 6, 450, 77, 40, 117, 59, 457, 36, 196, 817, 134, 86, 49, 515}, +{18, 16, 60, 68, 101, 167, 191, 118, 35, 121, 9, 212, 55, 0, 126, 1, 24, 647, 199, 146, 520, 107, 628, 621, 363, 71, 21, 28, 346, 92, 806, 727}, +{352, 230, 217, 531, 160, 93, 36, 669, 748, 854, 689, 258, 137, 871, 728, 699, 752, 251, 574, 202, 373, 351, 228, 120, 717, 260, 144, 219, 268, 82, 816, 1}, +{15, 515, 700, 753, 13, 23, 0, 51, 8, 1, 4, 82, 165, 77, 110, 33, 10, 180, 5, 202, 11, 22, 120, 12, 9, 197, 115, 93, 403, 141, 40, 351}, +{0, 9, 101, 217, 35, 88, 352, 100, 39, 175, 30, 68, 562, 752, 13, 317, 252, 115, 180, 197, 64, 1, 83, 141, 65, 213, 165, 230, 194, 36, 28, 265}, +{32, 64, 5, 470, 288, 90, 21, 147, 0, 95, 356, 22, 20, 519, 835, 312, 819, 18, 247, 182, 11, 97, 13, 4, 387, 49, 43, 298, 316, 48, 107, 7}, +{16, 14, 24, 1, 7, 2, 35, 0, 5, 50, 18, 69, 46, 12, 58, 75, 9, 67, 70, 163, 21, 54, 38, 48, 223, 502, 281, 37, 140, 60, 28, 10}, +{18, 265, 9, 252, 39, 195, 354, 411, 1, 16, 132, 101, 121, 682, 167, 203, 5, 363, 146, 593, 35, 333, 21, 271, 60, 13, 100, 0, 156, 327, 7, 520}, +{4, 13, 1, 115, 141, 23, 2, 180, 5, 0, 51, 3, 217, 202, 77, 15, 33, 269, 341, 318, 317, 21, 165, 515, 11, 10, 197, 365, 9, 137, 64, 352}, +{7, 24, 16, 14, 71, 35, 18, 92, 140, 189, 108, 149, 68, 60, 69, 150, 2, 230, 97, 66, 0, 458, 67, 1, 65, 251, 38, 314, 388, 267, 36, 46}, +{1, 22, 31, 36, 0, 2, 44, 5, 141, 105, 180, 170, 12, 64, 13, 98, 86, 55, 23, 21, 28, 164, 115, 127, 10, 125, 128, 4, 9, 239, 352, 197}, +{66, 7, 97, 2, 192, 20, 52, 43, 135, 74, 560, 107, 104, 0, 750, 147, 414, 29, 580, 173, 324, 376, 226, 194, 77, 174, 204, 38, 356, 64, 16, 470}, +{0, 101, 9, 68, 35, 124, 24, 65, 39, 16, 252, 100, 154, 166, 28, 364, 149, 694, 30, 88, 55, 346, 1, 419, 71, 439, 265, 289, 22, 21, 175, 158}, +{39, 9, 100, 30, 127, 0, 737, 856, 31, 836, 827, 254, 98, 931, 166, 88, 93, 1, 44, 190, 131, 228, 120, 395, 625, 385, 863, 264, 219, 373, 110, 28}, +{5, 17, 2, 3, 21, 45, 14, 155, 48, 32, 38, 1, 328, 181, 186, 46, 23, 51, 12, 61, 227, 29, 106, 54, 99, 133, 62, 832, 13, 37, 514, 543}, +{131, 613, 30, 224, 228, 716, 274, 100, 827, 406, 219, 856, 39, 190, 31, 88, 1, 166, 9, 44, 829, 863, 931, 93, 0, 187, 625, 924, 127, 98, 137, 254}, +{352, 217, 64, 141, 752, 269, 180, 864, 437, 372, 954, 115, 498, 177, 77, 349, 317, 318, 579, 291, 947, 197, 247, 0, 23, 717, 237, 304, 128, 457, 776, 678}, +{141, 217, 180, 317, 352, 115, 15, 341, 1, 23, 13, 365, 515, 752, 2, 64, 0, 5, 498, 700, 372, 165, 51, 237, 753, 77, 244, 197, 137, 4, 21, 253}, +{5, 2, 17, 14, 1, 45, 3, 38, 21, 29, 181, 58, 46, 48, 50, 133, 114, 171, 61, 155, 32, 6, 186, 281, 361, 12, 36, 54, 4, 13, 52, 514}, +{6, 2, 119, 25, 790, 4, 45, 483, 655, 113, 1, 29, 76, 26, 32, 19, 887, 17, 128, 0, 292, 833, 59, 61, 106, 64, 77, 814, 14, 151, 84, 42}, +{13, 23, 2, 0, 51, 4, 1, 115, 141, 3, 5, 180, 33, 217, 77, 9, 202, 11, 7, 15, 10, 6, 317, 64, 21, 197, 515, 165, 102, 128, 22, 269}, +{13, 23, 51, 202, 21, 5, 1, 15, 141, 165, 120, 2, 115, 12, 32, 0, 515, 128, 318, 64, 125, 700, 4, 403, 197, 453, 180, 457, 3, 7, 10, 6}, +{9, 39, 31, 30, 0, 127, 1, 44, 100, 131, 98, 187, 385, 276, 88, 442, 219, 908, 254, 116, 49, 166, 935, 28, 201, 36, 141, 827, 137, 299, 284, 21}, +{22, 49, 28, 109, 9, 185, 105, 95, 1, 131, 159, 272, 36, 67, 86, 254, 39, 55, 35, 0, 505, 31, 83, 169, 208, 327, 286, 98, 168, 535, 312, 708}, +{5, 1, 2, 21, 0, 12, 48, 22, 10, 14, 36, 3, 32, 17, 23, 54, 86, 38, 4, 51, 13, 37, 137, 50, 65, 281, 114, 45, 28, 99, 58, 202}, +{141, 269, 352, 82, 217, 351, 180, 854, 372, 922, 752, 1, 15, 260, 317, 318, 515, 202, 64, 700, 120, 349, 954, 753, 77, 35, 67, 717, 898, 137, 365, 115}, +{144, 203, 613, 418, 326, 406, 96, 669, 137, 679, 1, 228, 494, 822, 840, 317, 36, 83, 855, 160, 817, 859, 856, 816, 217, 831, 345, 93, 876, 77, 44, 251}, +{15, 13, 515, 23, 700, 753, 51, 1, 33, 0, 202, 21, 2, 5, 180, 141, 120, 165, 217, 82, 12, 117, 4, 352, 269, 197, 115, 32, 3, 9, 134, 260}, +{13, 23, 115, 1, 0, 51, 4, 77, 2, 33, 15, 141, 10, 5, 341, 180, 515, 3, 217, 202, 9, 365, 317, 64, 700, 102, 11, 165, 197, 22, 753, 7}, +{531, 943, 373, 160, 728, 93, 206, 260, 261, 559, 964, 269, 717, 535, 332, 384, 365, 295, 110, 533, 141, 10, 180, 352, 244, 137, 120, 55, 959, 564, 36, 253}, +{1, 31, 36, 170, 22, 55, 44, 10, 86, 64, 127, 0, 2, 98, 301, 164, 740, 338, 237, 143, 5, 125, 116, 13, 242, 141, 299, 180, 23, 169, 105, 12}, +{13, 23, 141, 77, 51, 4, 64, 32, 33, 202, 115, 269, 102, 128, 21, 0, 177, 180, 318, 90, 40, 10, 7, 5, 137, 15, 217, 352, 9, 291, 59, 22}, +{202, 120, 260, 318, 77, 15, 450, 269, 1, 82, 33, 23, 141, 13, 51, 515, 351, 128, 700, 5, 64, 326, 137, 21, 102, 110, 753, 494, 93, 523, 817, 165}, +{523, 899, 102, 33, 730, 15, 23, 403, 719, 117, 153, 13, 515, 51, 475, 4, 700, 5, 453, 817, 196, 753, 494, 40, 202, 120, 1, 2, 450, 457, 17, 421}, +{202, 403, 494, 450, 120, 817, 523, 475, 318, 453, 33, 402, 128, 77, 13, 51, 260, 576, 342, 102, 15, 23, 515, 4, 700, 5, 82, 753, 326, 210, 137, 615}, +{2, 29, 112, 66, 7, 52, 70, 151, 58, 87, 135, 5, 74, 226, 307, 6, 14, 186, 1, 45, 549, 172, 644, 25, 113, 287, 46, 155, 334, 64, 294, 97}, +{1, 77, 349, 291, 260, 120, 652, 102, 5, 39, 64, 269, 9, 33, 340, 342, 13, 98, 888, 698, 23, 296, 100, 318, 51, 202, 87, 137, 638, 128, 50, 850}, +{1, 13, 15, 2, 0, 4, 23, 515, 5, 141, 180, 3, 700, 341, 115, 51, 753, 269, 77, 901, 197, 352, 217, 33, 21, 11, 365, 6, 165, 202, 7, 317}, +{7, 14, 16, 2, 46, 5, 70, 58, 1, 38, 24, 35, 92, 163, 0, 75, 21, 18, 50, 54, 140, 12, 87, 220, 155, 69, 171, 23, 60, 9, 13, 307}, +{2, 29, 66, 226, 135, 7, 87, 74, 52, 278, 6, 75, 222, 220, 294, 70, 97, 1, 145, 25, 172, 262, 324, 38, 69, 112, 331, 92, 5, 14, 140, 26}, +{15, 515, 700, 753, 33, 77, 117, 4, 1, 102, 134, 40, 153, 11, 13, 196, 217, 21, 5, 51, 23, 115, 32, 3, 2, 202, 141, 137, 128, 291, 48, 177}, +{15, 217, 82, 515, 351, 141, 317, 1, 13, 700, 260, 77, 110, 120, 115, 854, 23, 753, 180, 51, 21, 36, 137, 922, 5, 64, 365, 352, 291, 202, 93, 341}, +{31, 190, 30, 373, 120, 110, 863, 88, 44, 127, 908, 856, 260, 318, 82, 98, 93, 187, 836, 717, 935, 39, 442, 131, 141, 254, 228, 219, 1, 968, 77, 116}, +{23, 13, 308, 9, 165, 115, 51, 21, 401, 125, 49, 39, 197, 391, 159, 254, 217, 743, 28, 438, 773, 629, 558, 386, 341, 95, 32, 317, 876, 679, 109, 166}, +{49, 5, 43, 165, 7, 0, 21, 104, 125, 22, 173, 422, 64, 13, 623, 102, 20, 18, 314, 95, 91, 141, 23, 31, 193, 51, 391, 900, 779, 558, 92, 232}, +{1, 4, 13, 2, 15, 0, 23, 515, 77, 3, 341, 33, 5, 700, 115, 51, 202, 753, 141, 180, 11, 10, 102, 217, 6, 901, 40, 7, 197, 318, 317, 365}, +{93, 843, 295, 120, 36, 160, 206, 261, 10, 137, 567, 110, 384, 141, 943, 268, 201, 332, 258, 55, 1, 180, 64, 116, 44, 144, 699, 203, 282, 31, 260, 373}, +{81, 7, 192, 426, 43, 173, 172, 104, 879, 91, 5, 712, 715, 526, 6, 97, 568, 95, 448, 66, 33, 861, 560, 32, 49, 20, 0, 636, 232, 825, 2, 22}, +{475, 403, 51, 453, 33, 102, 13, 23, 494, 202, 0, 196, 15, 77, 153, 18, 4, 117, 515, 450, 318, 22, 730, 128, 700, 421, 65, 753, 269, 402, 134, 817}, +{141, 269, 260, 318, 202, 120, 352, 349, 82, 351, 1, 5, 854, 137, 64, 291, 15, 922, 180, 851, 32, 77, 515, 372, 21, 700, 7, 217, 13, 947, 33, 753}, +{15, 515, 700, 753, 1, 13, 0, 2, 4, 23, 3, 5, 180, 115, 197, 12, 51, 165, 217, 10, 961, 9, 6, 141, 352, 21, 8, 7, 33, 77, 457, 120}, +{39, 166, 9, 30, 0, 101, 274, 404, 252, 333, 190, 100, 158, 438, 310, 88, 68, 265, 656, 21, 1, 530, 329, 344, 49, 539, 625, 254, 13, 131, 48, 419}, +{0, 1, 28, 9, 22, 12, 65, 83, 67, 36, 5, 2, 50, 55, 96, 109, 16, 13, 24, 23, 21, 238, 49, 18, 285, 160, 128, 39, 69, 114, 7, 323}, +{15, 515, 700, 1, 0, 753, 23, 2, 13, 51, 5, 180, 115, 6, 3, 9, 197, 12, 457, 120, 7, 165, 901, 82, 4, 21, 8, 141, 31, 33, 719, 341}, +{9, 39, 30, 0, 28, 166, 22, 49, 180, 1, 352, 35, 317, 158, 88, 141, 498, 131, 115, 345, 752, 128, 228, 217, 100, 83, 219, 930, 13, 251, 365, 36}, +{5, 61, 45, 2, 80, 29, 311, 209, 6, 17, 58, 1, 151, 106, 454, 667, 243, 70, 52, 496, 287, 592, 255, 738, 64, 74, 483, 14, 27, 32, 112, 19}, +{31, 125, 22, 44, 299, 456, 685, 242, 599, 116, 170, 28, 0, 1, 492, 393, 506, 144, 558, 10, 268, 301, 239, 23, 13, 36, 963, 367, 55, 206, 105, 95}, +{187, 258, 926, 574, 839, 93, 228, 860, 406, 219, 871, 160, 137, 531, 224, 116, 120, 902, 669, 201, 36, 131, 44, 144, 843, 533, 318, 384, 442, 1, 434, 268}, +{7, 107, 75, 16, 87, 9, 64, 177, 24, 18, 291, 77, 349, 141, 60, 232, 23, 0, 51, 269, 132, 14, 5, 21, 70, 32, 678, 112, 126, 121, 71, 947}, +{15, 515, 700, 753, 1, 0, 2, 13, 5, 3, 23, 180, 4, 115, 901, 51, 6, 8, 961, 9, 7, 10, 12, 82, 197, 22, 141, 341, 33, 120, 365, 457}, +{13, 23, 51, 1, 5, 202, 2, 12, 15, 21, 165, 141, 0, 115, 3, 4, 32, 515, 197, 10, 180, 318, 128, 120, 64, 700, 6, 7, 403, 269, 457, 137}, +{1, 2, 0, 77, 64, 3, 141, 13, 33, 15, 23, 10, 6, 102, 5, 515, 180, 4, 117, 7, 700, 165, 11, 217, 269, 40, 753, 115, 128, 17, 197, 134}, +{345, 531, 332, 269, 260, 317, 717, 752, 373, 351, 180, 352, 728, 82, 10, 365, 160, 533, 217, 143, 498, 251, 244, 93, 341, 901, 36, 1, 141, 898, 55, 864}, +{16, 7, 33, 189, 92, 77, 388, 60, 140, 35, 102, 24, 14, 1, 230, 21, 150, 117, 733, 314, 18, 915, 71, 13, 108, 134, 5, 64, 69, 2, 98, 22}, +{142, 202, 234, 178, 5, 786, 77, 49, 70, 0, 416, 450, 639, 878, 1, 48, 21, 929, 147, 259, 315, 455, 198, 120, 12, 481, 163, 113, 846, 329, 318, 22}, +{81, 715, 192, 0, 173, 712, 681, 104, 636, 91, 74, 20, 750, 370, 7, 718, 95, 879, 22, 43, 825, 560, 422, 64, 207, 49, 172, 18, 397, 10, 426, 319}, +{13, 23, 15, 51, 515, 0, 700, 753, 4, 1, 961, 2, 10, 115, 457, 11, 33, 453, 3, 5, 9, 40, 12, 197, 165, 77, 401, 475, 64, 102, 22, 569}, +{64, 297, 5, 445, 95, 61, 250, 311, 80, 34, 17, 312, 45, 2, 86, 472, 58, 14, 180, 53, 22, 151, 869, 738, 247, 237, 29, 1, 128, 165, 21, 288}, +{16, 24, 18, 71, 7, 35, 118, 92, 14, 154, 60, 68, 0, 149, 28, 302, 124, 150, 55, 175, 2, 9, 97, 1, 429, 20, 108, 273, 22, 65, 43, 126}, +{195, 360, 156, 771, 132, 163, 626, 687, 591, 371, 883, 146, 121, 846, 70, 586, 379, 13, 293, 98, 407, 48, 761, 296, 354, 18, 31, 1, 55, 49, 21, 105}, +{202, 13, 77, 23, 318, 33, 51, 0, 4, 141, 5, 21, 217, 32, 291, 102, 64, 128, 15, 10, 9, 494, 269, 137, 515, 403, 1, 31, 117, 700, 120, 317}, +{7, 192, 97, 81, 172, 66, 426, 173, 43, 715, 712, 232, 861, 879, 104, 330, 568, 298, 74, 893, 885, 526, 387, 825, 92, 140, 91, 14, 636, 6, 5, 448}, +{2, 1, 14, 6, 67, 7, 65, 69, 24, 36, 66, 124, 108, 83, 38, 29, 22, 86, 0, 18, 484, 5, 28, 46, 12, 10, 25, 302, 150, 16, 650, 74}, +{33, 77, 13, 202, 102, 4, 0, 23, 128, 51, 141, 64, 318, 22, 403, 269, 137, 10, 15, 40, 494, 117, 32, 59, 11, 153, 1, 21, 177, 196, 515, 115}, +{269, 141, 318, 77, 349, 291, 217, 202, 33, 15, 372, 304, 515, 22, 102, 177, 351, 700, 352, 120, 5, 137, 10, 317, 260, 753, 64, 851, 854, 403, 49, 21}, +{6, 74, 66, 85, 138, 25, 87, 42, 135, 26, 226, 222, 280, 29, 75, 500, 220, 278, 792, 70, 19, 2, 1, 294, 204, 64, 32, 145, 853, 112, 52, 174}, +{9, 0, 105, 39, 16, 18, 1, 101, 272, 31, 127, 98, 24, 518, 333, 252, 310, 28, 68, 737, 846, 371, 158, 916, 938, 49, 30, 7, 286, 35, 301, 455}, +{2, 1, 14, 67, 24, 46, 83, 108, 69, 29, 38, 103, 114, 36, 6, 133, 18, 0, 28, 7, 65, 52, 236, 75, 50, 398, 5, 309, 135, 16, 278, 160}, +{22, 1, 28, 105, 49, 95, 0, 2, 67, 55, 36, 239, 168, 159, 65, 35, 14, 170, 320, 164, 9, 7, 10, 5, 114, 12, 83, 64, 194, 109, 24, 301}, +{7, 66, 172, 97, 92, 140, 232, 568, 298, 14, 192, 314, 16, 380, 135, 324, 2, 330, 74, 38, 357, 448, 126, 69, 35, 5, 107, 6, 387, 60, 204, 572}, +{2, 29, 1, 14, 5, 6, 46, 133, 114, 50, 52, 26, 218, 108, 19, 13, 366, 236, 27, 45, 70, 17, 58, 23, 86, 51, 137, 65, 112, 38, 25, 12}, +{6, 1, 74, 25, 2, 26, 29, 66, 42, 19, 75, 14, 388, 67, 108, 70, 52, 85, 103, 65, 38, 138, 357, 133, 114, 594, 324, 516, 603, 96, 309, 69}, +{22, 9, 28, 1, 36, 49, 109, 105, 86, 95, 131, 31, 169, 39, 0, 141, 272, 159, 44, 55, 98, 180, 13, 30, 185, 115, 83, 128, 352, 137, 64, 208}, +{203, 822, 326, 23, 77, 859, 403, 494, 576, 39, 473, 182, 33, 1, 691, 100, 18, 217, 13, 817, 411, 447, 363, 102, 93, 966, 96, 478, 291, 704, 310, 120}, +{15, 515, 700, 753, 33, 77, 117, 4, 102, 134, 115, 153, 13, 1, 40, 217, 11, 196, 341, 2, 5, 3, 23, 317, 365, 0, 21, 291, 32, 51, 12, 569}, +{15, 515, 700, 753, 13, 0, 23, 1, 8, 82, 51, 165, 197, 120, 180, 2, 9, 33, 4, 110, 5, 12, 10, 260, 351, 386, 141, 7, 457, 475, 93, 901}, +{1, 23, 13, 15, 51, 0, 21, 2, 515, 5, 141, 180, 120, 165, 700, 202, 197, 4, 753, 12, 33, 9, 7, 82, 115, 93, 3, 352, 260, 6, 110, 48}, +{15, 515, 700, 753, 0, 1, 2, 5, 3, 4, 8, 13, 180, 341, 10, 23, 7, 6, 9, 51, 77, 197, 961, 115, 165, 82, 120, 31, 22, 202, 457, 217}, +{559, 661, 922, 564, 141, 533, 10, 317, 373, 110, 143, 269, 244, 260, 332, 261, 93, 642, 752, 295, 351, 876, 531, 843, 180, 206, 728, 384, 352, 1, 434, 120}, +{15, 515, 1, 0, 700, 2, 13, 23, 753, 5, 51, 180, 3, 165, 12, 6, 197, 115, 4, 9, 7, 21, 719, 8, 457, 82, 141, 120, 33, 22, 901, 10}, +{198, 234, 0, 325, 5, 77, 202, 416, 20, 147, 32, 43, 639, 315, 49, 61, 450, 455, 142, 21, 113, 230, 22, 318, 725, 342, 207, 13, 95, 904, 494, 10}, +{447, 264, 363, 9, 411, 676, 682, 1, 156, 664, 821, 478, 166, 354, 812, 39, 100, 905, 382, 897, 98, 18, 759, 404, 31, 101, 724, 5, 265, 223, 88, 13}, +{24, 14, 69, 16, 35, 18, 2, 7, 108, 189, 71, 67, 267, 149, 1, 46, 68, 83, 38, 140, 0, 236, 251, 9, 388, 60, 133, 103, 65, 28, 29, 50}, +{16, 7, 35, 20, 14, 18, 109, 2, 43, 120, 107, 60, 1, 121, 326, 907, 553, 77, 13, 147, 23, 82, 68, 260, 0, 403, 5, 24, 202, 126, 265, 199}, +{30, 131, 187, 276, 31, 44, 613, 442, 39, 9, 190, 228, 1, 839, 116, 935, 908, 219, 127, 88, 244, 224, 110, 137, 93, 201, 98, 141, 36, 567, 0, 856}, +{98, 223, 1, 393, 812, 265, 100, 421, 593, 834, 697, 48, 51, 410, 791, 382, 21, 88, 31, 284, 9, 125, 96, 293, 230, 23, 213, 217, 656, 689, 541, 5}, +{98, 51, 127, 219, 616, 258, 105, 293, 395, 421, 924, 512, 31, 308, 23, 201, 116, 44, 301, 272, 763, 276, 125, 13, 453, 170, 401, 295, 261, 944, 115, 567}, +{253, 110, 951, 352, 811, 206, 332, 180, 141, 244, 282, 10, 854, 417, 642, 638, 559, 752, 143, 911, 260, 55, 93, 533, 499, 498, 661, 120, 351, 959, 564, 341}, +{49, 9, 159, 254, 272, 158, 0, 131, 28, 39, 627, 105, 327, 286, 22, 518, 688, 578, 68, 347, 374, 101, 224, 424, 95, 35, 219, 24, 16, 364, 65, 344}, +{105, 22, 131, 272, 98, 286, 327, 109, 374, 239, 28, 95, 320, 219, 9, 224, 55, 127, 187, 36, 578, 169, 64, 185, 538, 1, 159, 10, 371, 634, 49, 616}, +{691, 478, 340, 1, 658, 914, 724, 363, 744, 698, 156, 772, 411, 296, 682, 447, 9, 284, 335, 98, 264, 303, 909, 21, 354, 410, 225, 13, 664, 686, 88, 919}, +{16, 24, 35, 18, 71, 7, 140, 108, 189, 267, 92, 60, 14, 230, 68, 69, 9, 1, 149, 46, 246, 191, 388, 167, 2, 0, 118, 236, 133, 21, 674, 5}, +{9, 0, 127, 31, 98, 371, 395, 39, 737, 49, 1, 44, 385, 272, 512, 28, 293, 242, 836, 761, 254, 299, 101, 16, 187, 22, 116, 158, 159, 131, 18, 21}, +{16, 18, 68, 0, 60, 35, 9, 101, 252, 28, 118, 24, 419, 55, 7, 109, 604, 71, 39, 121, 22, 364, 14, 158, 191, 167, 925, 126, 329, 21, 92, 49}, +{116, 268, 203, 93, 206, 692, 551, 31, 417, 940, 499, 8, 473, 44, 202, 523, 959, 0, 120, 137, 559, 22, 450, 403, 576, 10, 728, 299, 13, 326, 51, 1}, +{225, 459, 744, 1, 919, 914, 691, 330, 622, 21, 141, 223, 5, 284, 934, 335, 88, 538, 340, 82, 385, 839, 363, 120, 478, 98, 48, 30, 64, 32, 686, 166}, +{5, 1, 2, 0, 14, 36, 21, 281, 12, 48, 50, 67, 22, 28, 54, 83, 24, 218, 38, 10, 181, 9, 32, 18, 65, 58, 45, 114, 430, 17, 99, 37}, +{137, 450, 202, 704, 120, 260, 326, 318, 968, 269, 851, 403, 291, 77, 23, 141, 182, 310, 494, 373, 351, 457, 82, 890, 349, 110, 60, 128, 817, 678, 105, 96}, +{15, 515, 700, 753, 4, 33, 13, 23, 77, 5, 40, 11, 102, 93, 1, 21, 110, 51, 82, 117, 141, 2, 10, 8, 32, 64, 120, 31, 202, 3, 217, 115}, +{15, 13, 1, 23, 515, 0, 51, 2, 700, 5, 753, 21, 180, 141, 165, 3, 12, 115, 197, 4, 7, 6, 457, 9, 352, 202, 33, 8, 719, 120, 77, 341}, +{219, 127, 258, 98, 276, 201, 131, 395, 944, 293, 116, 284, 567, 31, 242, 105, 137, 935, 295, 44, 403, 860, 51, 224, 576, 456, 9, 371, 578, 475, 202, 512}, +{16, 7, 18, 35, 60, 0, 14, 20, 118, 28, 68, 22, 2, 24, 1, 92, 158, 107, 5, 49, 154, 126, 109, 12, 43, 10, 55, 6, 677, 71, 21, 168}, +{93, 728, 531, 160, 559, 373, 574, 120, 295, 860, 533, 269, 717, 260, 926, 902, 258, 318, 36, 201, 261, 434, 851, 137, 617, 141, 187, 352, 843, 384, 332, 251}, +{28, 0, 1, 9, 22, 109, 83, 39, 49, 12, 36, 67, 55, 5, 96, 2, 128, 30, 158, 69, 21, 23, 160, 208, 35, 13, 65, 323, 50, 141, 194, 238}, +{23, 13, 51, 1, 5, 15, 141, 21, 0, 2, 165, 515, 202, 700, 12, 197, 180, 120, 32, 115, 4, 753, 64, 9, 7, 269, 6, 3, 125, 386, 48, 453}, +{5, 21, 13, 49, 14, 20, 7, 23, 43, 32, 1, 0, 652, 48, 713, 22, 38, 2, 16, 132, 955, 107, 12, 279, 24, 888, 197, 640, 70, 303, 18, 638}, +{9, 0, 28, 39, 1, 30, 35, 101, 22, 67, 83, 141, 49, 175, 36, 68, 55, 88, 13, 251, 10, 69, 23, 158, 180, 115, 64, 100, 217, 65, 345, 166}, +{260, 120, 82, 269, 5, 450, 351, 1, 202, 141, 854, 13, 77, 922, 32, 33, 137, 4, 23, 125, 291, 21, 15, 515, 165, 349, 177, 700, 318, 326, 180, 753}, +{121, 16, 18, 35, 363, 101, 60, 20, 107, 14, 68, 259, 621, 55, 604, 43, 7, 252, 9, 364, 126, 0, 167, 191, 5, 407, 132, 28, 199, 419, 146, 10}, +{13, 23, 51, 1, 15, 0, 2, 141, 5, 515, 12, 21, 700, 115, 165, 180, 4, 753, 3, 197, 202, 32, 9, 120, 7, 8, 6, 11, 37, 10, 457, 269}, +{201, 144, 206, 443, 418, 203, 435, 96, 335, 459, 187, 1, 88, 332, 330, 321, 269, 934, 30, 372, 822, 521, 268, 326, 44, 523, 382, 141, 410, 264, 494, 473}, +{31, 44, 276, 201, 116, 131, 284, 662, 567, 144, 9, 489, 98, 295, 268, 434, 0, 30, 137, 39, 93, 1, 187, 22, 219, 918, 110, 299, 141, 36, 224, 384}, +{520, 478, 664, 1, 264, 604, 9, 167, 777, 759, 411, 0, 806, 724, 48, 21, 101, 68, 647, 936, 363, 223, 118, 682, 410, 18, 100, 16, 252, 98, 265, 13}, +{23, 70, 21, 87, 60, 75, 120, 182, 163, 379, 92, 18, 7, 937, 71, 121, 446, 132, 24, 98, 931, 126, 107, 77, 795, 195, 115, 44, 411, 146, 51, 850}, +{39, 9, 0, 737, 127, 31, 846, 98, 1, 827, 105, 310, 371, 30, 254, 100, 44, 18, 395, 242, 272, 101, 385, 916, 836, 16, 265, 131, 938, 93, 166, 557}, +{279, 20, 43, 126, 107, 7, 92, 16, 356, 362, 60, 595, 246, 359, 598, 35, 0, 683, 939, 653, 121, 97, 125, 441, 399, 392, 150, 199, 48, 230, 14, 649}, +{206, 417, 93, 959, 499, 728, 8, 559, 120, 473, 137, 141, 10, 564, 31, 260, 44, 450, 203, 341, 253, 244, 373, 116, 143, 638, 268, 180, 352, 110, 318, 940}, +{259, 465, 147, 132, 590, 687, 534, 199, 581, 146, 941, 427, 107, 640, 279, 178, 121, 5, 195, 150, 522, 955, 198, 35, 786, 929, 798, 142, 1, 21, 325, 626}, +{523, 15, 120, 450, 202, 515, 403, 51, 817, 700, 13, 753, 23, 457, 33, 899, 128, 64, 730, 102, 494, 342, 115, 719, 453, 196, 49, 99, 318, 421, 308, 5}, +{141, 559, 10, 244, 365, 564, 661, 180, 253, 143, 752, 110, 55, 317, 533, 341, 901, 93, 373, 206, 535, 160, 82, 922, 260, 36, 531, 964, 352, 332, 261, 197}, +{219, 258, 98, 127, 276, 964, 943, 137, 843, 535, 201, 935, 131, 860, 261, 295, 284, 567, 206, 44, 116, 31, 253, 492, 203, 332, 160, 615, 36, 93, 55, 692}, +{0, 319, 422, 207, 945, 693, 577, 887, 32, 804, 95, 344, 104, 904, 61, 20, 5, 43, 7, 725, 113, 510, 306, 102, 49, 263, 153, 426, 33, 83, 22, 9}, +{1, 22, 0, 5, 12, 2, 36, 21, 28, 86, 49, 105, 9, 10, 23, 13, 141, 95, 31, 55, 128, 37, 51, 4, 83, 202, 3, 64, 96, 7, 32, 44}, +{15, 515, 13, 700, 1, 0, 753, 2, 23, 3, 4, 5, 51, 10, 115, 197, 6, 33, 12, 9, 165, 7, 8, 77, 11, 961, 180, 269, 141, 22, 120, 457}, +{15, 1, 23, 120, 77, 13, 515, 51, 141, 202, 700, 180, 110, 137, 260, 753, 326, 5, 128, 102, 0, 21, 2, 165, 269, 33, 197, 450, 318, 217, 93, 115}, +{15, 515, 1, 700, 0, 753, 13, 2, 23, 180, 51, 5, 120, 4, 9, 115, 197, 12, 7, 165, 21, 33, 6, 82, 3, 8, 523, 901, 31, 141, 457, 260}, +{16, 18, 24, 7, 92, 35, 60, 75, 9, 13, 71, 14, 0, 108, 50, 21, 126, 121, 1, 140, 23, 5, 132, 146, 2, 12, 128, 10, 64, 141, 70, 87}, +{180, 341, 901, 15, 515, 1, 365, 700, 0, 2, 197, 753, 115, 4, 10, 13, 752, 5, 3, 8, 165, 317, 141, 23, 143, 873, 44, 31, 569, 55, 93, 6}, +{9, 0, 175, 35, 101, 28, 39, 67, 68, 1, 65, 83, 30, 69, 364, 336, 22, 114, 55, 124, 194, 158, 100, 289, 252, 166, 64, 345, 103, 36, 50, 88}, +{64, 165, 180, 197, 115, 247, 217, 237, 21, 13, 32, 316, 22, 141, 352, 72, 288, 304, 95, 225, 76, 391, 386, 16, 468, 90, 49, 35, 365, 640, 372, 23}, +{15, 515, 700, 13, 753, 1, 0, 2, 23, 4, 5, 3, 115, 51, 141, 197, 12, 10, 180, 961, 7, 9, 21, 33, 217, 6, 8, 165, 457, 11, 77, 341}, +{132, 121, 199, 146, 60, 279, 493, 640, 407, 598, 126, 195, 534, 581, 955, 590, 107, 5, 150, 35, 522, 49, 259, 16, 18, 360, 156, 0, 147, 362, 21, 167}, +{0, 1, 28, 9, 22, 5, 36, 12, 65, 24, 67, 96, 2, 83, 18, 50, 114, 55, 21, 16, 7, 10, 23, 14, 13, 160, 137, 51, 48, 218, 103, 69}, +{93, 120, 957, 77, 30, 968, 459, 110, 137, 160, 613, 102, 202, 352, 373, 141, 31, 372, 217, 330, 190, 318, 269, 260, 203, 44, 28, 473, 228, 177, 863, 704}, +{15, 515, 700, 0, 753, 1, 13, 23, 2, 51, 5, 9, 120, 82, 4, 7, 901, 197, 10, 8, 260, 180, 341, 12, 33, 6, 3, 523, 165, 102, 115, 141}, +{206, 417, 8, 141, 499, 44, 244, 93, 31, 10, 137, 253, 559, 116, 728, 144, 120, 564, 269, 638, 203, 352, 143, 260, 341, 752, 268, 717, 951, 180, 160, 110}, +{530, 254, 228, 1, 96, 21, 406, 39, 827, 31, 669, 840, 613, 829, 137, 679, 166, 98, 23, 51, 960, 438, 131, 93, 48, 224, 219, 317, 310, 36, 876, 190}, +{15, 515, 700, 753, 13, 457, 0, 197, 719, 1, 165, 82, 23, 8, 120, 730, 2, 10, 12, 180, 134, 5, 9, 141, 260, 4, 351, 51, 115, 3, 341, 899}, +{0, 16, 68, 9, 24, 28, 18, 35, 252, 109, 39, 419, 124, 158, 154, 55, 101, 71, 22, 118, 60, 7, 49, 65, 333, 14, 1, 10, 329, 364, 677, 346}, +{1, 15, 13, 23, 515, 51, 120, 0, 700, 180, 2, 165, 5, 753, 141, 197, 21, 33, 202, 102, 260, 4, 9, 12, 7, 326, 137, 450, 115, 6, 82, 110}, +{535, 253, 352, 564, 110, 365, 82, 180, 341, 10, 854, 533, 55, 898, 244, 901, 873, 141, 752, 143, 642, 559, 498, 317, 36, 951, 115, 964, 638, 282, 661, 197}, +{31, 44, 125, 338, 116, 64, 242, 36, 1, 10, 55, 22, 456, 237, 180, 13, 299, 164, 506, 86, 23, 165, 558, 143, 0, 762, 492, 479, 844, 546, 93, 8}, +{13, 23, 4, 1, 202, 2, 0, 51, 115, 77, 141, 180, 5, 15, 217, 3, 33, 11, 515, 317, 9, 10, 102, 21, 700, 341, 365, 318, 269, 64, 32, 128}, +{9, 39, 0, 166, 68, 101, 28, 364, 30, 158, 562, 35, 175, 65, 333, 154, 49, 404, 706, 124, 21, 252, 274, 168, 190, 289, 100, 570, 16, 1, 310, 346}, +{15, 515, 700, 753, 341, 13, 0, 23, 1, 33, 141, 4, 260, 82, 77, 51, 351, 180, 9, 5, 115, 137, 10, 217, 11, 120, 102, 40, 349, 269, 202, 854} +#else { 202,403,51,450,318,23,120,13,494,5,523,260,77,21,15,128,48,141,33,817,137,269,12,102,1,475,4,326,7,32,453,64,196,115,730,49,165,2,82,342,6,401,180,31,899,59,402,351,197,17,125,457,14,386,40,3,61,58,37,221,95,16,99,719,98,20,10,854,117,153,27,576,134,341,308,216,11,194,30,24,922,285,9,50,86,65,19,615,391,44,75,237,177,90,352,93,56,22,18,116,70,96,247,291,45,110,105,60,57,54,43,36,0,217,421,203,46,629,569,365,210,92,69,66,38,28,144,551 }, { 13,115,51,23,141,217,269,137,318,202,77,21,317,5,64,4,291,2,352,7,32,33,6,372,0,48,365,3,102,349,12,341,177,180,10,237,9,221,403,165,752,22,11,244,28,308,15,128,247,197,49,16,494,125,98,40,120,498,31,90,304,143,95,93,437,196,144,86,44,864,153,18,678,342,901,39,24,30,203,160,117,105,475,14,482,253,457,873,59,35,579,36,569,450,206,72,99,17,717,401,241,453,110,546,201,83,421,61,37,326,260,509,284,275,96,8,109,57,391,386,468,134,82,961,822,576,89,68 }, { 29,58,262,74,287,52,151,331,171,500,396,334,75,27,635,220,53,1,26,409,6,324,5,70,145,223,163,112,73,50,45,549,445,113,297,19,675,651,46,61,502,307,14,17,34,573,186,80,394,436,583,315,138,38,21,767,250,491,820,350,64,2,32,357,42,852,25,764,309,67,802,96,631,48,606,780,243,881,103,241,115,807,13,4,155,181,11,106,611,614,278,153,23,108,69,845,841,308,400,72,853,200,66,196,226,237,587,632,24,281,785,133,128,125,117,380,95,474,294,83,197,90,161,134,366,236,760,311 }, @@ -967,3 +1964,7 @@ { 23,13,51,4,115,202,5,217,77,141,1,11,180,2,317,0,3,7,33,269,318,15,365,341,21,9,102,10,32,6,40,12,352,177,22,197,403,64,165,128,901,59,752,31,494,137,308,291,28,8,18,349,401,16,125,90,30,14,237,498,372,93,37,98,153,49,453,17,36,873,44,475,457,39,342,196,210,24,48,326,569,386,421,247,95,203,120,509,275,116,391,961,117,244,110,143,57,304,144,216,482,719,134,139,468,86,523,55,221,450,67,76,50,253,35,105,260,65,437,373,730,72,859,629,46,692,576,111 }, { 39,9,166,364,68,101,158,333,0,154,562,28,404,30,65,124,252,35,175,274,344,310,190,706,49,289,570,100,168,438,694,419,346,703,826,55,16,24,439,21,88,149,254,577,429,810,109,159,962,857,671,212,455,656,22,610,95,194,1,336,747,13,125,67,36,131,530,865,48,71,625,793,10,589,23,64,841,265,484,539,86,224,558,350,69,237,420,51,835,96,272,105,406,677,165,228,83,18,31,141,114,286,557,221,347,115,137,169,722,778,7,391,98,818,816,308,840,634,709,44,185,128,960,777,143,258,669,60 }, { 15,341,13,33,23,77,141,4,0,351,1,260,102,51,82,9,40,349,854,11,115,217,269,137,180,202,922,5,901,22,10,117,21,365,318,197,120,352,64,12,7,153,177,59,291,32,128,2,165,196,372,36,403,317,457,28,18,8,16,304,30,14,450,31,898,37,3,752,48,134,139,494,421,6,453,401,719,90,86,569,523,110,24,55,475,210,49,44,386,17,730,95,247,244,961,143,125,308,342,817,629,98,498,93,96,76,39,275,509,326,99,285,373,57,237,35,402,160,111,253,105,391,221,116,899,72,127,661 } +#endif +}}; +} // namespace rgbcx::BC1 +// clang-format on \ No newline at end of file diff --git a/src/rgbcx/BC1/Tables.cpp b/src/rgbcx/BC1/Tables.cpp deleted file mode 100644 index 937bf5b..0000000 --- a/src/rgbcx/BC1/Tables.cpp +++ /dev/null @@ -1,1317 +0,0 @@ -// rgbcx.h v1.12 -// High-performance scalar BC1-5 encoders. Public Domain or MIT license (you choose - see below), written by Richard Geldreich 2020 . - -#include "Tables.h" - -const float g_midpoint5[32] = {.015686f, .047059f, .078431f, .111765f, .145098f, .176471f, .207843f, .241176f, .274510f, .305882f, .337255f, - .370588f, .403922f, .435294f, .466667f, .5f, .533333f, .564706f, .596078f, .629412f, .662745f, .694118f, - .725490f, .758824f, .792157f, .823529f, .854902f, .888235f, .921569f, .952941f, .984314f, 1e+37f}; -const float g_midpoint6[64] = {.007843f, .023529f, .039216f, .054902f, .070588f, .086275f, .101961f, .117647f, .133333f, .149020f, .164706f, .180392f, .196078f, - .211765f, .227451f, .245098f, .262745f, .278431f, .294118f, .309804f, .325490f, .341176f, .356863f, .372549f, .388235f, .403922f, - .419608f, .435294f, .450980f, .466667f, .482353f, .500000f, .517647f, .533333f, .549020f, .564706f, .580392f, .596078f, .611765f, - .627451f, .643137f, .658824f, .674510f, .690196f, .705882f, .721569f, .737255f, .754902f, .772549f, .788235f, .803922f, .819608f, - .835294f, .850980f, .866667f, .882353f, .898039f, .913725f, .929412f, .945098f, .960784f, .976471f, .992157f, 1e+37f}; - -// All total orderings for 16 pixels 2-bit selectors. -// BC1 selector order 0, 2, 3, 1 (i.e. the selectors are reordered into linear order). -const uint8_t g_unique_total_orders4[NUM_UNIQUE_TOTAL_ORDERINGS4][4] = { - {0, 8, 2, 6}, {4, 3, 9, 0}, {4, 8, 1, 3}, {12, 0, 3, 1}, {11, 3, 2, 0}, {6, 4, 6, 0}, {7, 5, 0, 4}, {6, 0, 8, 2}, {1, 0, 0, 15}, {3, 0, 8, 5}, - {1, 1, 13, 1}, {13, 1, 2, 0}, {0, 14, 1, 1}, {0, 15, 1, 0}, {0, 13, 0, 3}, {16, 0, 0, 0}, {4, 3, 4, 5}, {8, 6, 0, 2}, {0, 10, 0, 6}, {10, 0, 4, 2}, - {7, 2, 1, 6}, {4, 7, 5, 0}, {1, 4, 7, 4}, {0, 14, 2, 0}, {2, 7, 2, 5}, {9, 0, 5, 2}, {9, 2, 2, 3}, {10, 0, 5, 1}, {2, 3, 7, 4}, {4, 9, 0, 3}, - {1, 5, 0, 10}, {1, 1, 6, 8}, {6, 6, 4, 0}, {11, 5, 0, 0}, {11, 2, 0, 3}, {4, 0, 10, 2}, {2, 3, 10, 1}, {1, 13, 1, 1}, {0, 14, 0, 2}, {2, 3, 3, 8}, - {12, 3, 1, 0}, {14, 0, 0, 2}, {9, 1, 3, 3}, {6, 4, 0, 6}, {1, 1, 5, 9}, {5, 9, 0, 2}, {2, 10, 1, 3}, {12, 0, 0, 4}, {4, 6, 6, 0}, {0, 6, 4, 6}, - {3, 7, 4, 2}, {0, 13, 3, 0}, {3, 10, 0, 3}, {10, 2, 1, 3}, {1, 12, 1, 2}, {2, 0, 13, 1}, {11, 0, 5, 0}, {12, 1, 3, 0}, {6, 4, 5, 1}, {10, 4, 2, 0}, - {3, 6, 1, 6}, {7, 3, 6, 0}, {10, 4, 0, 2}, {10, 0, 2, 4}, {0, 5, 9, 2}, {0, 9, 3, 4}, {6, 4, 2, 4}, {3, 4, 7, 2}, {3, 3, 5, 5}, {4, 2, 9, 1}, - {6, 2, 8, 0}, {3, 5, 3, 5}, {4, 10, 1, 1}, {10, 1, 3, 2}, {5, 7, 0, 4}, {5, 3, 7, 1}, {6, 8, 1, 1}, {8, 8, 0, 0}, {11, 1, 0, 4}, {14, 1, 0, 1}, - {9, 3, 2, 2}, {8, 2, 1, 5}, {0, 0, 2, 14}, {3, 3, 9, 1}, {10, 1, 5, 0}, {8, 3, 1, 4}, {1, 5, 8, 2}, {6, 1, 9, 0}, {3, 2, 1, 10}, {3, 11, 1, 1}, - {7, 6, 3, 0}, {9, 0, 3, 4}, {5, 2, 5, 4}, {0, 2, 3, 11}, {15, 0, 0, 1}, {0, 6, 6, 4}, {3, 4, 9, 0}, {4, 7, 0, 5}, {0, 4, 4, 8}, {0, 13, 2, 1}, - {2, 4, 1, 9}, {3, 2, 5, 6}, {10, 6, 0, 0}, {3, 5, 6, 2}, {8, 0, 4, 4}, {1, 3, 6, 6}, {7, 7, 0, 2}, {6, 1, 4, 5}, {0, 11, 1, 4}, {2, 2, 8, 4}, - {0, 1, 2, 13}, {15, 0, 1, 0}, {7, 2, 6, 1}, {8, 1, 7, 0}, {1, 8, 4, 3}, {2, 13, 1, 0}, {1, 0, 7, 8}, {14, 2, 0, 0}, {1, 8, 1, 6}, {9, 3, 3, 1}, - {0, 0, 7, 9}, {4, 4, 1, 7}, {9, 0, 6, 1}, {10, 2, 4, 0}, {1, 7, 3, 5}, {0, 3, 8, 5}, {5, 2, 4, 5}, {1, 2, 5, 8}, {0, 8, 7, 1}, {10, 3, 2, 1}, - {12, 0, 4, 0}, {2, 1, 4, 9}, {5, 2, 2, 7}, {1, 9, 3, 3}, {15, 1, 0, 0}, {6, 3, 4, 3}, {9, 5, 0, 2}, {1, 6, 9, 0}, {6, 6, 0, 4}, {13, 2, 1, 0}, - {5, 1, 8, 2}, {0, 5, 11, 0}, {7, 1, 0, 8}, {1, 2, 12, 1}, {0, 3, 3, 10}, {7, 4, 2, 3}, {5, 1, 4, 6}, {7, 0, 3, 6}, {3, 12, 0, 1}, {3, 4, 5, 4}, - {1, 10, 0, 5}, {7, 4, 3, 2}, {10, 5, 0, 1}, {13, 3, 0, 0}, {2, 5, 4, 5}, {3, 10, 1, 2}, {5, 1, 2, 8}, {14, 0, 1, 1}, {1, 5, 4, 6}, {1, 4, 5, 6}, - {2, 3, 11, 0}, {11, 0, 4, 1}, {11, 2, 2, 1}, {5, 3, 8, 0}, {1, 3, 10, 2}, {0, 1, 13, 2}, {3, 1, 4, 8}, {4, 2, 4, 6}, {1, 5, 6, 4}, {2, 1, 11, 2}, - {1, 2, 9, 4}, {4, 7, 3, 2}, {6, 2, 5, 3}, {7, 2, 2, 5}, {8, 1, 4, 3}, {3, 2, 8, 3}, {12, 1, 0, 3}, {7, 8, 1, 0}, {7, 0, 2, 7}, {5, 10, 0, 1}, - {0, 2, 14, 0}, {2, 9, 3, 2}, {7, 0, 0, 9}, {11, 1, 4, 0}, {10, 4, 1, 1}, {2, 2, 9, 3}, {5, 7, 2, 2}, {1, 3, 1, 11}, {13, 2, 0, 1}, {4, 2, 8, 2}, - {2, 3, 1, 10}, {4, 2, 5, 5}, {7, 0, 7, 2}, {10, 0, 0, 6}, {0, 8, 5, 3}, {4, 4, 0, 8}, {12, 4, 0, 0}, {0, 1, 14, 1}, {8, 0, 1, 7}, {5, 1, 5, 5}, - {11, 0, 3, 2}, {0, 4, 1, 11}, {0, 8, 8, 0}, {0, 2, 5, 9}, {7, 3, 2, 4}, {7, 8, 0, 1}, {1, 0, 3, 12}, {7, 4, 5, 0}, {1, 6, 7, 2}, {7, 6, 1, 2}, - {9, 6, 1, 0}, {12, 2, 0, 2}, {4, 1, 6, 5}, {4, 0, 1, 11}, {8, 4, 4, 0}, {13, 0, 1, 2}, {8, 6, 2, 0}, {4, 12, 0, 0}, {2, 7, 5, 2}, {2, 0, 5, 9}, - {5, 4, 5, 2}, {3, 8, 5, 0}, {7, 3, 3, 3}, {4, 4, 8, 0}, {2, 1, 3, 10}, {5, 0, 1, 10}, {6, 4, 3, 3}, {4, 9, 1, 2}, {1, 4, 0, 11}, {11, 3, 1, 1}, - {4, 0, 12, 0}, {13, 0, 0, 3}, {6, 1, 6, 3}, {9, 0, 4, 3}, {8, 0, 0, 8}, {8, 4, 0, 4}, {0, 12, 1, 3}, {0, 4, 10, 2}, {3, 4, 8, 1}, {1, 3, 8, 4}, - {9, 2, 5, 0}, {5, 7, 4, 0}, {1, 0, 11, 4}, {4, 10, 0, 2}, {1, 3, 12, 0}, {6, 9, 0, 1}, {5, 0, 9, 2}, {5, 9, 2, 0}, {13, 1, 0, 2}, {9, 3, 4, 0}, - {9, 4, 0, 3}, {3, 1, 12, 0}, {2, 4, 3, 7}, {1, 2, 13, 0}, {2, 2, 4, 8}, {6, 8, 0, 2}, {9, 2, 1, 4}, {9, 5, 1, 1}, {2, 0, 4, 10}, {5, 4, 0, 7}, - {0, 0, 6, 10}, {1, 2, 0, 13}, {4, 7, 2, 3}, {6, 5, 5, 0}, {3, 3, 1, 9}, {1, 6, 1, 8}, {12, 2, 1, 1}, {4, 4, 5, 3}, {1, 0, 6, 9}, {0, 6, 10, 0}, - {4, 8, 3, 1}, {4, 3, 2, 7}, {2, 1, 7, 6}, {1, 9, 1, 5}, {3, 1, 3, 9}, {8, 7, 1, 0}, {1, 2, 3, 10}, {14, 1, 1, 0}, {5, 4, 4, 3}, {3, 7, 0, 6}, - {7, 4, 1, 4}, {3, 7, 5, 1}, {1, 1, 0, 14}, {0, 10, 3, 3}, {0, 4, 3, 9}, {1, 7, 7, 1}, {2, 0, 10, 4}, {5, 8, 0, 3}, {6, 7, 3, 0}, {0, 8, 4, 4}, - {5, 7, 3, 1}, {7, 9, 0, 0}, {7, 6, 2, 1}, {0, 4, 5, 7}, {6, 3, 5, 2}, {1, 2, 1, 12}, {5, 2, 0, 9}, {8, 5, 0, 3}, {4, 6, 1, 5}, {1, 1, 7, 7}, - {10, 5, 1, 0}, {1, 2, 8, 5}, {1, 8, 2, 5}, {5, 1, 0, 10}, {6, 9, 1, 0}, {13, 0, 2, 1}, {8, 3, 5, 0}, {6, 3, 6, 1}, {2, 11, 3, 0}, {3, 7, 3, 3}, - {1, 5, 2, 8}, {7, 5, 2, 2}, {0, 6, 7, 3}, {13, 1, 1, 1}, {5, 3, 4, 4}, {7, 2, 7, 0}, {5, 8, 3, 0}, {3, 13, 0, 0}, {0, 7, 9, 0}, {8, 0, 3, 5}, - {1, 3, 7, 5}, {4, 0, 2, 10}, {12, 0, 1, 3}, {1, 7, 6, 2}, {3, 9, 0, 4}, {7, 2, 0, 7}, {0, 1, 7, 8}, {2, 1, 8, 5}, {0, 13, 1, 2}, {0, 8, 1, 7}, - {5, 0, 11, 0}, {5, 6, 2, 3}, {0, 3, 0, 13}, {2, 3, 4, 7}, {5, 6, 3, 2}, {4, 2, 10, 0}, {3, 3, 7, 3}, {7, 2, 5, 2}, {1, 1, 11, 3}, {12, 3, 0, 1}, - {5, 1, 1, 9}, {1, 15, 0, 0}, {9, 7, 0, 0}, {9, 1, 2, 4}, {0, 7, 3, 6}, {3, 0, 13, 0}, {3, 0, 11, 2}, {0, 6, 5, 5}, {8, 2, 2, 4}, {6, 10, 0, 0}, - {4, 8, 4, 0}, {0, 0, 3, 13}, {0, 4, 12, 0}, {7, 1, 6, 2}, {3, 5, 0, 8}, {8, 0, 6, 2}, {6, 2, 3, 5}, {2, 10, 0, 4}, {4, 11, 0, 1}, {6, 1, 5, 4}, - {5, 1, 3, 7}, {0, 11, 3, 2}, {4, 6, 0, 6}, {2, 6, 0, 8}, {3, 1, 7, 5}, {2, 14, 0, 0}, {2, 9, 2, 3}, {0, 3, 4, 9}, {11, 0, 1, 4}, {13, 0, 3, 0}, - {8, 3, 0, 5}, {0, 5, 3, 8}, {5, 11, 0, 0}, {0, 1, 4, 11}, {2, 1, 9, 4}, {3, 4, 4, 5}, {7, 1, 2, 6}, {12, 2, 2, 0}, {9, 4, 1, 2}, {6, 0, 2, 8}, - {4, 6, 2, 4}, {11, 2, 3, 0}, {3, 2, 2, 9}, {10, 3, 1, 2}, {1, 1, 2, 12}, {0, 5, 2, 9}, {0, 1, 11, 4}, {6, 2, 4, 4}, {2, 8, 2, 4}, {0, 9, 4, 3}, - {11, 0, 2, 3}, {0, 2, 11, 3}, {6, 0, 7, 3}, {0, 3, 6, 7}, {4, 5, 5, 2}, {1, 2, 6, 7}, {7, 5, 1, 3}, {9, 0, 2, 5}, {2, 6, 4, 4}, {4, 1, 9, 2}, - {4, 8, 2, 2}, {1, 12, 3, 0}, {0, 9, 6, 1}, {0, 10, 6, 0}, {3, 1, 5, 7}, {2, 13, 0, 1}, {2, 2, 1, 11}, {3, 6, 0, 7}, {5, 6, 5, 0}, {5, 5, 4, 2}, - {4, 0, 3, 9}, {3, 4, 1, 8}, {0, 11, 2, 3}, {2, 12, 1, 1}, {7, 1, 3, 5}, {7, 0, 9, 0}, {8, 0, 8, 0}, {1, 0, 2, 13}, {3, 3, 10, 0}, {2, 4, 4, 6}, - {2, 3, 8, 3}, {1, 10, 5, 0}, {7, 3, 0, 6}, {2, 9, 0, 5}, {1, 4, 6, 5}, {6, 6, 3, 1}, {5, 6, 0, 5}, {6, 3, 0, 7}, {3, 10, 2, 1}, {2, 5, 5, 4}, - {3, 8, 4, 1}, {1, 14, 0, 1}, {10, 3, 3, 0}, {3, 5, 7, 1}, {1, 1, 3, 11}, {2, 4, 0, 10}, {9, 3, 1, 3}, {5, 10, 1, 0}, {3, 0, 6, 7}, {3, 1, 9, 3}, - {11, 2, 1, 2}, {5, 3, 3, 5}, {0, 5, 1, 10}, {4, 1, 11, 0}, {10, 2, 0, 4}, {7, 6, 0, 3}, {2, 7, 0, 7}, {4, 2, 2, 8}, {6, 1, 7, 2}, {4, 9, 2, 1}, - {0, 0, 8, 8}, {3, 7, 2, 4}, {9, 6, 0, 1}, {0, 12, 4, 0}, {6, 7, 1, 2}, {0, 7, 2, 7}, {1, 0, 10, 5}, {0, 0, 14, 2}, {2, 7, 3, 4}, {5, 0, 0, 11}, - {7, 7, 1, 1}, {6, 2, 7, 1}, {4, 5, 3, 4}, {3, 5, 1, 7}, {5, 9, 1, 1}, {6, 2, 1, 7}, {3, 2, 0, 11}, {0, 11, 0, 5}, {3, 11, 2, 0}, {10, 1, 4, 1}, - {7, 0, 4, 5}, {11, 4, 0, 1}, {10, 3, 0, 3}, {0, 2, 4, 10}, {0, 15, 0, 1}, {0, 11, 5, 0}, {6, 7, 2, 1}, {1, 12, 2, 1}, {4, 1, 3, 8}, {1, 0, 13, 2}, - {1, 8, 5, 2}, {7, 0, 1, 8}, {3, 12, 1, 0}, {9, 2, 4, 1}, {1, 7, 4, 4}, {11, 4, 1, 0}, {4, 3, 8, 1}, {2, 8, 4, 2}, {1, 11, 3, 1}, {1, 1, 4, 10}, - {4, 10, 2, 0}, {8, 2, 5, 1}, {1, 0, 9, 6}, {5, 3, 2, 6}, {0, 9, 7, 0}, {10, 2, 2, 2}, {5, 8, 1, 2}, {8, 7, 0, 1}, {0, 3, 12, 1}, {1, 0, 1, 14}, - {4, 8, 0, 4}, {3, 8, 0, 5}, {4, 6, 5, 1}, {0, 9, 5, 2}, {10, 2, 3, 1}, {2, 3, 9, 2}, {1, 0, 12, 3}, {11, 3, 0, 2}, {4, 5, 2, 5}, {0, 2, 12, 2}, - {9, 1, 0, 6}, {9, 2, 0, 5}, {1, 2, 7, 6}, {4, 7, 4, 1}, {0, 12, 2, 2}, {0, 0, 0, 16}, {2, 8, 3, 3}, {3, 6, 2, 5}, {0, 6, 3, 7}, {7, 5, 4, 0}, - {3, 3, 3, 7}, {3, 3, 0, 10}, {5, 0, 6, 5}, {0, 0, 10, 6}, {8, 5, 3, 0}, {8, 1, 5, 2}, {6, 0, 9, 1}, {11, 1, 2, 2}, {2, 11, 2, 1}, {9, 5, 2, 0}, - {3, 0, 4, 9}, {2, 2, 12, 0}, {2, 6, 6, 2}, {2, 1, 13, 0}, {6, 0, 5, 5}, {2, 0, 14, 0}, {2, 11, 1, 2}, {4, 4, 7, 1}, {2, 0, 11, 3}, {3, 1, 1, 11}, - {2, 9, 4, 1}, {3, 7, 6, 0}, {14, 0, 2, 0}, {1, 10, 4, 1}, {8, 0, 7, 1}, {3, 6, 5, 2}, {0, 3, 11, 2}, {2, 5, 6, 3}, {11, 1, 3, 1}, {6, 5, 3, 2}, - {3, 8, 1, 4}, {0, 2, 7, 7}, {2, 10, 2, 2}, {1, 6, 2, 7}, {11, 0, 0, 5}, {12, 1, 1, 2}, {12, 1, 2, 1}, {0, 7, 1, 8}, {0, 3, 9, 4}, {0, 2, 1, 13}, - {7, 1, 4, 4}, {10, 1, 0, 5}, {4, 0, 8, 4}, {5, 2, 7, 2}, {0, 2, 0, 14}, {4, 3, 7, 2}, {2, 7, 1, 6}, {1, 2, 2, 11}, {6, 3, 3, 4}, {1, 14, 1, 0}, - {2, 4, 6, 4}, {5, 3, 6, 2}, {5, 3, 5, 3}, {8, 4, 1, 3}, {1, 3, 0, 12}, {3, 5, 2, 6}, {1, 8, 7, 0}, {0, 7, 4, 5}, {2, 1, 6, 7}, {4, 11, 1, 0}, - {7, 2, 4, 3}, {6, 1, 3, 6}, {4, 5, 4, 3}, {2, 11, 0, 3}, {1, 5, 7, 3}, {12, 0, 2, 2}, {5, 0, 4, 7}, {1, 13, 0, 2}, {7, 7, 2, 0}, {4, 1, 7, 4}, - {4, 5, 0, 7}, {5, 0, 5, 6}, {6, 5, 4, 1}, {2, 4, 2, 8}, {1, 10, 1, 4}, {6, 3, 1, 6}, {3, 3, 8, 2}, {0, 7, 7, 2}, {4, 4, 2, 6}, {1, 1, 8, 6}, - {1, 12, 0, 3}, {2, 1, 12, 1}, {1, 9, 2, 4}, {1, 11, 0, 4}, {2, 5, 2, 7}, {10, 0, 3, 3}, {4, 6, 3, 3}, {3, 7, 1, 5}, {1, 9, 0, 6}, {7, 1, 7, 1}, - {1, 6, 5, 4}, {9, 2, 3, 2}, {6, 2, 2, 6}, {2, 2, 2, 10}, {8, 3, 3, 2}, {0, 1, 8, 7}, {2, 0, 8, 6}, {0, 3, 1, 12}, {9, 4, 2, 1}, {9, 4, 3, 0}, - {6, 2, 6, 2}, {1, 8, 0, 7}, {5, 1, 10, 0}, {0, 5, 5, 6}, {8, 2, 4, 2}, {2, 3, 2, 9}, {6, 0, 3, 7}, {2, 2, 6, 6}, {2, 6, 2, 6}, {1, 13, 2, 0}, - {9, 3, 0, 4}, {7, 3, 5, 1}, {6, 5, 2, 3}, {5, 2, 6, 3}, {2, 0, 12, 2}, {5, 7, 1, 3}, {8, 1, 3, 4}, {3, 1, 10, 2}, {1, 0, 15, 0}, {0, 8, 0, 8}, - {5, 0, 7, 4}, {4, 4, 6, 2}, {0, 1, 0, 15}, {10, 0, 1, 5}, {7, 3, 4, 2}, {4, 9, 3, 0}, {2, 5, 7, 2}, {3, 4, 2, 7}, {8, 3, 2, 3}, {5, 1, 6, 4}, - {0, 10, 2, 4}, {6, 6, 1, 3}, {6, 0, 0, 10}, {4, 4, 3, 5}, {1, 3, 9, 3}, {7, 5, 3, 1}, {3, 0, 7, 6}, {1, 8, 6, 1}, {4, 3, 0, 9}, {3, 11, 0, 2}, - {6, 0, 6, 4}, {0, 1, 3, 12}, {0, 4, 2, 10}, {5, 5, 6, 0}, {4, 1, 4, 7}, {8, 1, 6, 1}, {5, 6, 4, 1}, {8, 4, 2, 2}, {4, 3, 1, 8}, {3, 0, 2, 11}, - {1, 11, 4, 0}, {0, 8, 3, 5}, {5, 1, 7, 3}, {7, 0, 8, 1}, {4, 3, 5, 4}, {4, 6, 4, 2}, {3, 2, 4, 7}, {1, 6, 3, 6}, {0, 7, 8, 1}, {3, 0, 1, 12}, - {9, 1, 4, 2}, {7, 4, 0, 5}, {1, 7, 0, 8}, {5, 4, 1, 6}, {9, 1, 5, 1}, {1, 1, 9, 5}, {4, 1, 1, 10}, {5, 3, 0, 8}, {2, 2, 5, 7}, {4, 0, 0, 12}, - {9, 0, 7, 0}, {3, 4, 0, 9}, {0, 2, 6, 8}, {8, 2, 0, 6}, {3, 2, 6, 5}, {4, 2, 6, 4}, {3, 6, 4, 3}, {2, 8, 6, 0}, {5, 0, 3, 8}, {0, 4, 0, 12}, - {0, 16, 0, 0}, {0, 9, 2, 5}, {4, 0, 11, 1}, {1, 6, 4, 5}, {0, 1, 6, 9}, {3, 4, 6, 3}, {3, 0, 10, 3}, {7, 0, 6, 3}, {1, 4, 9, 2}, {1, 5, 3, 7}, - {8, 5, 2, 1}, {0, 12, 0, 4}, {7, 2, 3, 4}, {0, 5, 6, 5}, {11, 1, 1, 3}, {6, 5, 0, 5}, {2, 1, 5, 8}, {1, 4, 11, 0}, {9, 1, 1, 5}, {0, 0, 13, 3}, - {5, 8, 2, 1}, {2, 12, 0, 2}, {3, 3, 6, 4}, {4, 1, 10, 1}, {4, 0, 5, 7}, {8, 1, 0, 7}, {5, 1, 9, 1}, {4, 3, 3, 6}, {0, 2, 2, 12}, {6, 3, 2, 5}, - {0, 0, 12, 4}, {1, 5, 1, 9}, {2, 6, 5, 3}, {3, 6, 3, 4}, {2, 12, 2, 0}, {1, 6, 8, 1}, {10, 1, 1, 4}, {1, 3, 4, 8}, {7, 4, 4, 1}, {1, 11, 1, 3}, - {1, 2, 10, 3}, {3, 9, 3, 1}, {8, 5, 1, 2}, {2, 10, 4, 0}, {4, 2, 0, 10}, {2, 7, 6, 1}, {8, 2, 3, 3}, {1, 5, 5, 5}, {3, 1, 0, 12}, {3, 10, 3, 0}, - {8, 0, 5, 3}, {0, 6, 8, 2}, {0, 3, 13, 0}, {0, 0, 16, 0}, {1, 9, 4, 2}, {4, 1, 8, 3}, {1, 6, 6, 3}, {0, 10, 5, 1}, {0, 1, 12, 3}, {4, 0, 6, 6}, - {3, 8, 3, 2}, {0, 5, 4, 7}, {1, 0, 14, 1}, {0, 4, 6, 6}, {3, 9, 1, 3}, {3, 5, 8, 0}, {3, 6, 6, 1}, {5, 4, 7, 0}, {3, 0, 12, 1}, {8, 6, 1, 1}, - {2, 9, 5, 0}, {6, 1, 1, 8}, {4, 1, 2, 9}, {3, 9, 4, 0}, {5, 2, 9, 0}, {0, 12, 3, 1}, {1, 4, 10, 1}, {4, 0, 7, 5}, {3, 1, 2, 10}, {5, 4, 2, 5}, - {5, 5, 5, 1}, {4, 2, 3, 7}, {1, 7, 5, 3}, {2, 8, 0, 6}, {8, 1, 2, 5}, {3, 8, 2, 3}, {6, 1, 2, 7}, {3, 9, 2, 2}, {9, 0, 0, 7}, {0, 8, 6, 2}, - {8, 4, 3, 1}, {0, 2, 8, 6}, {6, 5, 1, 4}, {2, 3, 5, 6}, {2, 10, 3, 1}, {0, 7, 0, 9}, {4, 2, 7, 3}, {2, 4, 8, 2}, {7, 1, 1, 7}, {2, 4, 7, 3}, - {2, 4, 10, 0}, {0, 1, 10, 5}, {4, 7, 1, 4}, {0, 10, 4, 2}, {9, 0, 1, 6}, {1, 9, 6, 0}, {3, 3, 4, 6}, {4, 5, 7, 0}, {5, 5, 2, 4}, {2, 8, 1, 5}, - {2, 3, 6, 5}, {0, 1, 1, 14}, {3, 2, 3, 8}, {10, 1, 2, 3}, {9, 1, 6, 0}, {3, 4, 3, 6}, {2, 2, 0, 12}, {0, 0, 9, 7}, {4, 0, 9, 3}, {7, 0, 5, 4}, - {4, 5, 6, 1}, {2, 5, 1, 8}, {2, 5, 9, 0}, {3, 5, 4, 4}, {1, 3, 11, 1}, {7, 1, 5, 3}, {3, 2, 7, 4}, {1, 4, 2, 9}, {1, 11, 2, 2}, {2, 2, 3, 9}, - {5, 0, 10, 1}, {3, 2, 11, 0}, {1, 10, 3, 2}, {8, 3, 4, 1}, {3, 6, 7, 0}, {0, 7, 5, 4}, {1, 3, 3, 9}, {2, 2, 10, 2}, {1, 9, 5, 1}, {0, 5, 0, 11}, - {3, 0, 3, 10}, {0, 4, 8, 4}, {2, 7, 7, 0}, {2, 0, 2, 12}, {1, 2, 11, 2}, {6, 3, 7, 0}, {0, 6, 2, 8}, {0, 10, 1, 5}, {0, 9, 0, 7}, {6, 4, 4, 2}, - {6, 0, 1, 9}, {1, 5, 10, 0}, {5, 4, 6, 1}, {5, 5, 3, 3}, {0, 0, 4, 12}, {0, 3, 2, 11}, {1, 4, 1, 10}, {3, 0, 9, 4}, {5, 5, 0, 6}, {1, 7, 8, 0}, - {2, 0, 3, 11}, {6, 4, 1, 5}, {10, 0, 6, 0}, {0, 6, 0, 10}, {0, 4, 11, 1}, {3, 1, 6, 6}, {2, 5, 8, 1}, {0, 2, 10, 4}, {3, 1, 11, 1}, {6, 6, 2, 2}, - {1, 1, 10, 4}, {2, 1, 2, 11}, {6, 1, 8, 1}, {0, 2, 13, 1}, {0, 7, 6, 3}, {6, 8, 2, 0}, {3, 0, 0, 13}, {4, 4, 4, 4}, {6, 2, 0, 8}, {7, 3, 1, 5}, - {0, 11, 4, 1}, {6, 7, 0, 3}, {2, 6, 3, 5}, {5, 2, 1, 8}, {7, 1, 8, 0}, {5, 5, 1, 5}, {1, 8, 3, 4}, {8, 2, 6, 0}, {6, 0, 10, 0}, {5, 6, 1, 4}, - {1, 4, 4, 7}, {2, 7, 4, 3}, {1, 4, 8, 3}, {5, 4, 3, 4}, {1, 10, 2, 3}, {2, 9, 1, 4}, {2, 2, 11, 1}, {2, 5, 0, 9}, {0, 0, 1, 15}, {0, 0, 11, 5}, - {0, 4, 7, 5}, {0, 1, 15, 0}, {2, 1, 0, 13}, {0, 3, 10, 3}, {8, 0, 2, 6}, {3, 3, 2, 8}, {3, 5, 5, 3}, {1, 7, 1, 7}, {1, 3, 2, 10}, {4, 0, 4, 8}, - {2, 0, 9, 5}, {1, 1, 1, 13}, {2, 2, 7, 5}, {2, 1, 10, 3}, {4, 2, 1, 9}, {4, 3, 6, 3}, {1, 3, 5, 7}, {2, 5, 3, 6}, {1, 0, 8, 7}, {5, 0, 2, 9}, - {2, 8, 5, 1}, {1, 6, 0, 9}, {0, 0, 5, 11}, {0, 4, 9, 3}, {2, 0, 7, 7}, {1, 7, 2, 6}, {2, 1, 1, 12}, {2, 4, 9, 1}, {0, 5, 7, 4}, {6, 0, 4, 6}, - {3, 2, 10, 1}, {0, 6, 1, 9}, {2, 6, 1, 7}, {0, 5, 8, 3}, {4, 1, 0, 11}, {1, 2, 4, 9}, {4, 1, 5, 6}, {6, 1, 0, 9}, {1, 4, 3, 8}, {4, 5, 1, 6}, - {1, 0, 5, 10}, {5, 3, 1, 7}, {0, 9, 1, 6}, {2, 0, 1, 13}, {2, 0, 6, 8}, {8, 1, 1, 6}, {1, 5, 9, 1}, {0, 6, 9, 1}, {0, 3, 5, 8}, {0, 2, 9, 5}, - {5, 2, 8, 1}, {1, 1, 14, 0}, {3, 2, 9, 2}, {5, 0, 8, 3}, {0, 5, 10, 1}, {5, 2, 3, 6}, {2, 6, 7, 1}, {2, 3, 0, 11}, {0, 1, 9, 6}, {1, 0, 4, 11}, - {3, 0, 5, 8}, {0, 0, 15, 1}, {2, 4, 5, 5}, {0, 3, 7, 6}, {2, 0, 0, 14}, {1, 1, 12, 2}, {2, 6, 8, 0}, {3, 1, 8, 4}, {0, 1, 5, 10}}; - -// All total orderings for 16 pixels [0,2] 2-bit selectors. -// BC1 selector order: 0, 1, 2 -// Note this is different from g_unique_total_orders4[], which reorders the selectors into linear order. -const uint8_t g_unique_total_orders3[NUM_UNIQUE_TOTAL_ORDERINGS3][3] = { - {6, 0, 10}, {3, 6, 7}, {3, 0, 13}, {13, 3, 0}, {12, 4, 0}, {9, 1, 6}, {2, 13, 1}, {4, 7, 5}, {7, 5, 4}, {9, 6, 1}, {7, 4, 5}, {8, 6, 2}, {16, 0, 0}, - {10, 6, 0}, {2, 7, 7}, {0, 0, 16}, {0, 3, 13}, {1, 15, 0}, {0, 2, 14}, {1, 4, 11}, {15, 1, 0}, {1, 12, 3}, {9, 2, 5}, {14, 1, 1}, {8, 2, 6}, {3, 3, 10}, - {4, 2, 10}, {14, 0, 2}, {0, 14, 2}, {1, 7, 8}, {6, 6, 4}, {11, 5, 0}, {6, 4, 6}, {11, 3, 2}, {4, 3, 9}, {7, 1, 8}, {10, 4, 2}, {12, 1, 3}, {11, 0, 5}, - {9, 3, 4}, {1, 0, 15}, {9, 0, 7}, {2, 6, 8}, {12, 2, 2}, {6, 2, 8}, {6, 8, 2}, {15, 0, 1}, {4, 8, 4}, {0, 4, 12}, {8, 5, 3}, {5, 9, 2}, {11, 2, 3}, - {12, 3, 1}, {6, 3, 7}, {1, 1, 14}, {2, 9, 5}, {1, 8, 7}, {4, 10, 2}, {7, 7, 2}, {13, 1, 2}, {0, 15, 1}, {3, 2, 11}, {7, 0, 9}, {4, 4, 8}, {3, 8, 5}, - {0, 5, 11}, {13, 2, 1}, {1, 10, 5}, {4, 11, 1}, {3, 10, 3}, {5, 10, 1}, {10, 2, 4}, {0, 6, 10}, {14, 2, 0}, {11, 4, 1}, {3, 12, 1}, {1, 13, 2}, {1, 5, 10}, - {5, 11, 0}, {12, 0, 4}, {8, 1, 7}, {6, 10, 0}, {3, 13, 0}, {7, 2, 7}, {0, 7, 9}, {5, 8, 3}, {0, 12, 4}, {11, 1, 4}, {13, 0, 3}, {0, 16, 0}, {5, 7, 4}, - {10, 3, 3}, {10, 0, 6}, {0, 13, 3}, {4, 6, 6}, {2, 8, 6}, {2, 5, 9}, {7, 8, 1}, {2, 1, 13}, {2, 0, 14}, {7, 3, 6}, {5, 1, 10}, {3, 11, 2}, {5, 4, 7}, - {8, 3, 5}, {10, 5, 1}, {6, 9, 1}, {1, 3, 12}, {4, 5, 7}, {2, 2, 12}, {4, 1, 11}, {0, 8, 8}, {4, 12, 0}, {6, 5, 5}, {8, 7, 1}, {5, 5, 6}, {3, 7, 6}, - {7, 9, 0}, {4, 9, 3}, {0, 10, 6}, {8, 0, 8}, {5, 3, 8}, {10, 1, 5}, {6, 1, 9}, {7, 6, 3}, {9, 5, 2}, {0, 1, 15}, {9, 7, 0}, {2, 14, 0}, {3, 4, 9}, - {8, 4, 4}, {9, 4, 3}, {0, 9, 7}, {1, 9, 6}, {3, 9, 4}, {5, 2, 9}, {2, 3, 11}, {5, 6, 5}, {1, 14, 1}, {6, 7, 3}, {2, 4, 10}, {2, 12, 2}, {8, 8, 0}, - {2, 10, 4}, {4, 0, 12}, {0, 11, 5}, {2, 11, 3}, {1, 11, 4}, {3, 5, 8}, {5, 0, 11}, {3, 1, 12}, {1, 2, 13}, {1, 6, 9}}; - -// For each total ordering, this table indicates which other total orderings are likely to improve quality using a least squares pass. Each array is sorted by -// usefulness. -const uint16_t g_best_total_orderings4[NUM_UNIQUE_TOTAL_ORDERINGS4][MAX_TOTAL_ORDERINGS4] = { -#if RGBCX_USE_SMALLER_TABLES - {202, 120, 13, 318, 15, 23, 403, 450, 5, 51, 260, 128, 77, 21, 33, 494, 515, 523, 4, 141, 269, 1, 2, 700, 137, 49, 48, 102, 7, 64, 753, 82}, - {13, 141, 23, 217, 115, 51, 77, 2, 64, 21, 0, 4, 5, 317, 137, 269, 202, 33, 318, 7, 291, 352, 9, 10, 3, 180, 32, 6, 365, 102, 341, 349}, - {29, 58, 262, 1, 52, 74, 6, 171, 5, 287, 151, 334, 27, 500, 75, 26, 331, 223, 53, 635, 220, 19, 50, 45, 46, 17, 14, 396, 163, 409, 324, 70}, - {40, 51, 33, 453, 14, 23, 62, 56, 12, 196, 730, 475, 153, 99, 403, 775, 117, 130, 585, 34, 4, 17, 162, 11, 139, 57, 102, 38, 108, 47, 123, 440}, - {33, 23, 51, 13, 102, 64, 202, 128, 12, 40, 15, 196, 153, 10, 1, 2, 77, 99, 141, 0, 515, 5, 117, 3, 120, 403, 700, 165, 22, 14, 269, 453}, - {13, 23, 51, 4, 77, 141, 202, 33, 115, 64, 32, 128, 0, 11, 177, 40, 15, 102, 2, 217, 7, 137, 269, 21, 90, 59, 515, 1, 180, 403, 22, 6}, - {26, 235, 19, 47, 648, 624, 78, 145, 27, 112, 122, 64, 444, 6, 630, 453, 25, 42, 65, 130, 711, 85, 390, 113, 416, 108, 665, 29, 730, 138, 644, 95}, - {64, 141, 352, 751, 217, 247, 237, 437, 177, 269, 86, 954, 947, 875, 32, 318, 95, 77, 304, 92, 597, 180, 232, 291, 128, 864, 349, 588, 372, 202, 312, 1}, - {642, 898, 180, 638, 901, 341, 82, 197, 10, 951, 15, 515, 165, 762, 700, 253, 811, 753, 752, 365, 143, 479, 244, 569, 8, 110, 351, 873, 55, 31, 499, 116}, - {221, 23, 51, 125, 438, 254, 13, 21, 39, 49, 308, 656, 0, 115, 530, 159, 158, 401, 30, 166, 912, 386, 165, 688, 518, 9, 105, 627, 424, 22, 421, 33}, - {143, 31, 1, 44, 197, 8, 180, 125, 116, 55, 13, 498, 23, 341, 638, 242, 93, 15, 2, 141, 0, 901, 752, 115, 36, 206, 165, 479, 338, 365, 515, 762}, - {12, 23, 51, 13, 14, 15, 37, 99, 515, 38, 700, 117, 2, 196, 134, 153, 753, 64, 54, 33, 128, 120, 21, 0, 328, 5, 139, 82, 453, 719, 457, 1}, - {13, 15, 23, 515, 961, 700, 457, 753, 51, 115, 4, 165, 197, 2, 38, 569, 1, 474, 0, 37, 99, 719, 5, 12, 629, 14, 11, 3, 33, 77, 64, 10}, - {15, 515, 700, 753, 1, 0, 2, 4, 3, 23, 134, 12, 961, 5, 10, 197, 11, 33, 82, 120, 457, 51, 165, 7, 6, 341, 217, 21, 77, 9, 40, 180}, - {13, 51, 23, 457, 719, 961, 730, 401, 165, 453, 0, 117, 386, 15, 134, 1, 758, 153, 12, 54, 515, 99, 11, 2, 700, 5, 753, 4, 308, 33, 6, 899}, - {134, 898, 82, 117, 13, 33, 77, 102, 23, 260, 341, 351, 120, 901, 197, 153, 961, 111, 196, 110, 180, 457, 854, 10, 450, 8, 165, 40, 4, 115, 0, 365}, - {60, 18, 126, 167, 35, 16, 191, 71, 24, 92, 121, 271, 68, 107, 212, 146, 118, 150, 199, 7, 21, 1, 9, 575, 727, 5, 566, 48, 0, 132, 108, 273}, - {62, 136, 129, 123, 128, 41, 162, 17, 249, 211, 214, 789, 618, 710, 38, 678, 248, 507, 57, 64, 152, 269, 119, 3, 177, 183, 597, 106, 4, 179, 216, 90}, - {403, 523, 51, 475, 494, 453, 817, 899, 202, 23, 450, 13, 421, 120, 102, 730, 33, 128, 4, 1, 805, 5, 7, 153, 757, 260, 318, 196, 77, 457, 326, 65}, - {4, 59, 3, 62, 12, 33, 56, 193, 27, 21, 102, 17, 40, 77, 76, 84, 32, 0, 6, 123, 119, 177, 128, 11, 18, 611, 605, 25, 13, 51, 73, 210}, - {43, 20, 319, 422, 414, 945, 0, 7, 819, 61, 5, 376, 325, 173, 804, 904, 470, 693, 97, 707, 14, 49, 22, 104, 147, 107, 95, 32, 426, 1, 330, 577}, - {13, 23, 51, 2, 0, 115, 4, 141, 217, 33, 10, 77, 1, 15, 64, 180, 3, 515, 7, 6, 22, 102, 11, 5, 40, 9, 165, 700, 202, 197, 317, 341}, - {28, 49, 0, 105, 1, 24, 65, 159, 35, 55, 95, 239, 16, 2, 109, 7, 9, 14, 170, 320, 347, 168, 424, 158, 10, 301, 124, 5, 67, 21, 64, 36}, - {15, 515, 700, 753, 0, 1, 13, 2, 117, 4, 12, 10, 5, 165, 457, 3, 9, 134, 11, 7, 6, 51, 77, 64, 961, 82, 33, 197, 14, 341, 120, 141}, - {7, 71, 14, 149, 97, 18, 60, 16, 150, 92, 398, 189, 140, 124, 24, 273, 35, 2, 69, 302, 154, 68, 0, 336, 517, 43, 66, 28, 118, 251, 230, 1}, - {4, 102, 33, 77, 40, 59, 11, 624, 210, 12, 128, 342, 5, 503, 91, 139, 64, 32, 25, 494, 202, 678, 416, 0, 403, 275, 21, 450, 196, 318, 523, 177}, - {25, 19, 42, 6, 122, 813, 256, 235, 85, 26, 436, 53, 297, 573, 680, 390, 445, 63, 27, 416, 80, 233, 65, 73, 389, 283, 45, 605, 194, 17, 250, 343}, - {402, 102, 202, 128, 33, 300, 403, 23, 12, 77, 40, 21, 342, 117, 483, 99, 25, 494, 6, 4, 63, 32, 84, 569, 139, 757, 475, 318, 19, 26, 196, 134}, - {158, 9, 0, 109, 39, 49, 65, 22, 35, 168, 55, 24, 68, 124, 159, 16, 185, 344, 333, 154, 254, 272, 175, 289, 1, 577, 95, 28, 105, 810, 30, 169}, - {197, 180, 115, 237, 498, 165, 2, 5, 287, 546, 400, 3, 61, 34, 509, 13, 297, 80, 341, 52, 45, 186, 58, 881, 23, 873, 468, 176, 64, 17, 311, 250}, - {120, 968, 373, 260, 704, 110, 450, 202, 137, 318, 77, 95, 269, 326, 217, 717, 661, 652, 851, 349, 93, 1, 518, 98, 827, 291, 21, 177, 82, 33, 848, 719}, - {44, 116, 144, 268, 434, 489, 367, 384, 98, 127, 918, 93, 948, 31, 206, 940, 855, 0, 203, 137, 9, 22, 617, 141, 332, 105, 393, 492, 959, 282, 299, 131}, - {13, 77, 23, 33, 51, 0, 64, 141, 102, 4, 2, 115, 1, 6, 202, 15, 10, 128, 269, 7, 177, 180, 3, 40, 22, 11, 515, 217, 117, 318, 700, 137}, - {15, 515, 700, 753, 4, 11, 141, 40, 165, 23, 64, 180, 13, 202, 32, 3, 51, 125, 5, 197, 21, 128, 0, 93, 77, 1, 120, 82, 269, 117, 110, 59}, - {176, 231, 585, 62, 34, 14, 412, 161, 56, 236, 527, 57, 17, 3, 51, 202, 4, 23, 369, 283, 128, 13, 472, 440, 84, 361, 136, 457, 381, 130, 719, 53}, - {9, 0, 180, 217, 237, 101, 141, 352, 88, 100, 230, 64, 175, 317, 115, 498, 68, 39, 30, 1, 702, 83, 213, 36, 365, 208, 752, 13, 252, 321, 952, 546}, - {28, 9, 22, 1, 49, 0, 109, 39, 83, 95, 86, 30, 13, 105, 128, 55, 141, 168, 158, 67, 31, 159, 208, 12, 96, 5, 185, 2, 160, 64, 137, 23}, - {72, 4, 38, 12, 51, 89, 477, 11, 57, 76, 401, 308, 23, 474, 99, 148, 413, 179, 59, 13, 431, 152, 54, 569, 17, 3, 205, 629, 197, 421, 405, 15}, - {457, 13, 23, 961, 15, 51, 515, 700, 165, 12, 753, 629, 11, 1, 719, 117, 0, 3, 2, 37, 569, 197, 40, 328, 33, 5, 153, 134, 99, 64, 38, 196}, - {254, 100, 310, 9, 30, 1, 39, 625, 166, 265, 190, 0, 272, 557, 131, 731, 31, 98, 578, 688, 404, 93, 101, 88, 49, 21, 127, 264, 44, 36, 252, 478}, - {51, 23, 12, 13, 15, 128, 99, 120, 10, 202, 515, 153, 64, 82, 700, 33, 165, 2, 5, 117, 403, 1, 141, 0, 3, 196, 37, 453, 753, 197, 260, 93}, - {38, 99, 542, 139, 453, 117, 196, 23, 457, 13, 328, 111, 37, 134, 961, 11, 12, 51, 40, 775, 587, 401, 474, 54, 153, 477, 41, 629, 33, 475, 14, 277}, - {6, 85, 25, 233, 343, 91, 26, 63, 138, 29, 19, 65, 283, 4, 81, 235, 42, 122, 605, 64, 648, 256, 174, 370, 74, 389, 718, 59, 45, 194, 445, 416}, - {49, 5, 97, 20, 197, 21, 18, 193, 0, 64, 408, 729, 173, 350, 43, 422, 165, 7, 14, 104, 61, 32, 509, 713, 523, 102, 120, 95, 125, 397, 35, 232}, - {144, 116, 268, 434, 384, 489, 367, 206, 93, 855, 940, 44, 98, 332, 617, 127, 959, 911, 137, 282, 203, 31, 22, 219, 141, 9, 131, 276, 417, 0, 1, 120}, - {17, 106, 64, 62, 32, 255, 136, 292, 476, 162, 129, 241, 123, 141, 41, 237, 720, 214, 209, 352, 519, 211, 186, 148, 752, 247, 507, 90, 21, 77, 197, 119}, - {2, 29, 52, 50, 5, 58, 14, 6, 27, 1, 366, 357, 45, 53, 17, 19, 171, 151, 26, 181, 133, 38, 218, 764, 287, 583, 61, 113, 3, 487, 600, 281}, - {130, 59, 196, 412, 381, 730, 711, 236, 77, 210, 202, 402, 453, 99, 401, 108, 361, 803, 291, 283, 153, 4, 57, 51, 128, 183, 14, 719, 503, 117, 23, 11}, - {13, 23, 51, 141, 77, 4, 33, 64, 115, 0, 217, 10, 180, 202, 2, 102, 11, 9, 15, 165, 40, 21, 128, 352, 22, 7, 197, 3, 317, 515, 269, 1}, - {23, 13, 202, 51, 120, 15, 21, 5, 141, 1, 128, 269, 137, 515, 64, 102, 125, 48, 98, 33, 260, 523, 318, 93, 700, 165, 450, 77, 2, 12, 403, 82}, - {1, 2, 14, 46, 29, 67, 38, 52, 5, 171, 58, 24, 103, 69, 96, 70, 83, 181, 54, 75, 163, 223, 16, 45, 112, 309, 155, 0, 186, 35, 18, 108}, - {15, 515, 700, 753, 13, 0, 1, 2, 153, 5, 23, 10, 117, 3, 9, 7, 134, 165, 12, 6, 341, 33, 4, 14, 77, 457, 115, 21, 719, 180, 217, 82}, - {197, 165, 509, 13, 391, 180, 308, 115, 23, 546, 5, 498, 2, 29, 3, 401, 901, 61, 34, 80, 14, 457, 250, 569, 237, 873, 38, 297, 45, 15, 468, 386}, - {19, 73, 27, 250, 200, 714, 444, 472, 26, 53, 34, 17, 813, 322, 283, 390, 128, 297, 78, 123, 432, 14, 436, 136, 106, 690, 57, 122, 389, 80, 503, 3}, - {3, 17, 21, 45, 62, 32, 38, 12, 155, 14, 2, 328, 5, 99, 401, 536, 828, 13, 227, 488, 106, 51, 719, 119, 540, 76, 165, 221, 115, 629, 209, 41}, - {115, 341, 873, 197, 365, 13, 901, 180, 569, 752, 317, 1, 10, 498, 143, 634, 261, 0, 509, 15, 943, 237, 44, 31, 116, 601, 165, 127, 282, 23, 141, 64}, - {453, 51, 23, 403, 33, 421, 475, 102, 15, 153, 196, 515, 13, 700, 117, 523, 12, 40, 753, 21, 4, 134, 0, 494, 670, 899, 22, 801, 730, 10, 11, 401}, - {23, 13, 51, 33, 12, 117, 153, 134, 453, 196, 15, 99, 515, 40, 14, 700, 128, 102, 11, 753, 77, 64, 403, 202, 0, 401, 475, 37, 65, 2, 3, 38}, - {2, 7, 5, 14, 70, 1, 29, 61, 52, 45, 6, 112, 66, 16, 21, 32, 592, 46, 38, 135, 87, 58, 186, 315, 290, 128, 113, 0, 64, 48, 227, 23}, - {33, 23, 102, 51, 128, 13, 64, 202, 141, 1, 77, 10, 153, 40, 196, 117, 2, 3, 0, 5, 15, 269, 403, 12, 137, 134, 318, 165, 120, 6, 453, 99}, - {16, 92, 7, 20, 43, 35, 126, 71, 60, 14, 107, 18, 68, 97, 0, 121, 279, 149, 24, 246, 191, 48, 118, 575, 55, 140, 362, 783, 230, 150, 375, 566}, - {13, 23, 4, 33, 77, 64, 51, 102, 141, 128, 32, 10, 0, 202, 40, 115, 59, 22, 90, 11, 177, 21, 291, 6, 7, 318, 180, 117, 137, 2, 95, 165}, - {507, 162, 129, 41, 4, 211, 62, 38, 123, 59, 57, 248, 183, 130, 99, 11, 3, 361, 202, 17, 402, 556, 266, 305, 803, 210, 128, 184, 152, 136, 313, 117}, - {643, 123, 193, 650, 802, 18, 25, 389, 718, 256, 65, 289, 84, 91, 619, 511, 415, 90, 235, 63, 57, 510, 324, 216, 862, 102, 6, 183, 108, 397, 217, 736}, - {13, 23, 15, 1, 515, 51, 0, 2, 700, 5, 753, 165, 141, 115, 12, 3, 4, 180, 21, 197, 457, 7, 6, 10, 120, 9, 33, 202, 77, 32, 8, 11}, - {23, 51, 13, 453, 64, 403, 12, 21, 5, 202, 128, 475, 165, 141, 523, 95, 125, 115, 3, 1, 4, 730, 120, 32, 2, 494, 180, 719, 457, 197, 450, 401}, - {204, 74, 135, 66, 6, 174, 192, 7, 138, 172, 85, 353, 348, 580, 280, 97, 95, 500, 29, 64, 426, 32, 87, 889, 65, 81, 25, 2, 52, 43, 568, 673}, - {35, 0, 68, 69, 24, 9, 1, 16, 65, 103, 149, 133, 18, 114, 28, 50, 83, 2, 189, 7, 46, 14, 101, 336, 175, 124, 251, 55, 71, 218, 38, 238}, - {16, 101, 0, 118, 9, 18, 24, 68, 35, 154, 71, 124, 60, 212, 191, 520, 55, 806, 694, 167, 28, 39, 364, 375, 1, 346, 252, 65, 604, 302, 22, 21}, - {0, 9, 16, 35, 1, 24, 68, 18, 65, 21, 103, 67, 13, 149, 28, 189, 71, 23, 101, 238, 114, 7, 335, 133, 486, 141, 22, 212, 48, 50, 30, 118}, - {13, 202, 23, 77, 33, 51, 128, 5, 21, 141, 115, 32, 102, 64, 4, 0, 318, 269, 10, 15, 291, 2, 494, 177, 11, 217, 3, 515, 22, 137, 6, 700}, - {16, 92, 60, 35, 7, 18, 24, 68, 150, 149, 14, 71, 0, 375, 97, 126, 118, 107, 230, 191, 246, 273, 140, 55, 175, 653, 9, 575, 2, 28, 566, 517}, - {76, 90, 21, 179, 316, 148, 205, 32, 464, 288, 184, 257, 245, 1, 89, 2, 460, 57, 152, 45, 38, 358, 645, 5, 12, 449, 350, 48, 37, 17, 4, 14}, - {19, 27, 26, 813, 80, 297, 17, 495, 436, 53, 73, 200, 4, 378, 250, 59, 106, 25, 45, 128, 361, 42, 113, 469, 122, 390, 77, 40, 736, 6, 11, 136}, - {6, 26, 235, 138, 19, 145, 112, 70, 331, 262, 25, 42, 52, 624, 27, 453, 122, 47, 500, 78, 648, 85, 29, 2, 630, 632, 409, 113, 50, 226, 108, 75}, - {7, 16, 14, 24, 92, 35, 18, 2, 46, 9, 60, 140, 0, 87, 50, 5, 54, 13, 12, 38, 171, 23, 126, 21, 58, 64, 1, 70, 128, 71, 220, 163}, - {90, 205, 257, 184, 32, 179, 460, 5, 245, 45, 2, 288, 769, 524, 57, 21, 152, 229, 17, 1, 497, 4, 292, 59, 619, 452, 432, 76, 476, 11, 266, 14}, - {15, 515, 700, 753, 4, 5, 11, 141, 13, 1, 33, 3, 0, 128, 202, 23, 180, 21, 2, 64, 269, 32, 117, 134, 120, 40, 102, 318, 153, 17, 137, 352}, - {47, 130, 711, 108, 453, 412, 730, 196, 390, 283, 78, 27, 51, 183, 381, 236, 128, 200, 719, 14, 153, 472, 503, 34, 59, 250, 3, 4, 57, 803, 123, 432}, - {12, 277, 51, 474, 111, 153, 23, 99, 13, 37, 961, 94, 629, 542, 569, 431, 79, 139, 38, 134, 117, 453, 33, 188, 196, 40, 115, 15, 11, 157, 401, 515}, - {17, 495, 469, 106, 26, 378, 80, 27, 161, 483, 19, 742, 527, 436, 383, 862, 73, 136, 53, 814, 297, 6, 119, 84, 62, 56, 25, 3, 209, 611, 4, 128}, - {81, 681, 636, 91, 0, 750, 370, 104, 718, 138, 18, 693, 173, 784, 29, 397, 348, 74, 192, 673, 174, 65, 6, 207, 64, 280, 306, 52, 671, 32, 355, 319}, - {15, 515, 700, 753, 33, 77, 4, 102, 115, 117, 40, 13, 1, 153, 134, 11, 5, 217, 23, 196, 2, 21, 3, 317, 32, 365, 0, 341, 291, 59, 12, 51}, - {0, 9, 28, 35, 68, 1, 65, 67, 101, 39, 69, 175, 16, 238, 13, 22, 96, 124, 18, 24, 251, 30, 55, 12, 23, 2, 50, 141, 114, 5, 154, 103}, - {23, 33, 77, 13, 117, 40, 11, 102, 64, 4, 51, 403, 153, 453, 10, 0, 196, 134, 128, 65, 12, 291, 86, 99, 95, 59, 15, 141, 202, 180, 137, 719}, - {214, 90, 289, 6, 874, 64, 25, 65, 235, 42, 751, 249, 256, 312, 194, 85, 746, 875, 174, 32, 525, 288, 519, 835, 247, 348, 233, 544, 217, 524, 437, 352}, - {1, 22, 2, 0, 36, 67, 28, 5, 49, 95, 12, 50, 168, 83, 105, 55, 7, 9, 14, 194, 103, 23, 114, 21, 584, 46, 10, 13, 38, 69, 208, 159}, - {269, 141, 13, 202, 33, 180, 318, 77, 291, 137, 102, 352, 128, 23, 349, 51, 31, 217, 372, 317, 125, 197, 44, 21, 11, 5, 901, 1, 18, 0, 4, 494}, - {435, 144, 274, 88, 203, 418, 30, 1, 190, 410, 96, 778, 100, 530, 521, 326, 466, 795, 686, 166, 960, 321, 382, 264, 367, 822, 131, 31, 692, 9, 213, 93}, - {76, 72, 90, 21, 37, 179, 12, 205, 32, 428, 148, 38, 308, 405, 4, 413, 57, 184, 749, 245, 316, 221, 54, 645, 288, 1, 152, 155, 464, 257, 2, 14}, - {77, 33, 64, 102, 13, 141, 23, 2, 40, 1, 51, 10, 0, 115, 6, 180, 202, 128, 4, 3, 177, 269, 15, 7, 22, 165, 291, 14, 217, 318, 137, 11}, - {397, 81, 4, 32, 65, 788, 693, 804, 681, 11, 249, 21, 91, 64, 690, 494, 3, 0, 422, 56, 348, 725, 194, 123, 23, 59, 523, 319, 61, 510, 95, 90}, - {60, 126, 16, 7, 92, 121, 314, 246, 35, 107, 150, 132, 14, 146, 24, 18, 199, 298, 232, 71, 359, 140, 672, 97, 392, 649, 5, 423, 95, 21, 22, 388}, - {15, 515, 141, 217, 115, 700, 13, 23, 120, 317, 753, 180, 33, 260, 110, 137, 341, 51, 1, 365, 4, 77, 64, 202, 0, 40, 36, 352, 197, 269, 10, 21}, - {111, 134, 117, 474, 23, 13, 961, 12, 569, 431, 37, 15, 51, 115, 515, 700, 277, 99, 753, 38, 197, 405, 457, 4, 72, 94, 629, 45, 11, 89, 54, 148}, - {23, 13, 51, 5, 1, 15, 2, 21, 12, 202, 141, 0, 515, 165, 120, 32, 4, 64, 700, 3, 115, 197, 269, 125, 753, 7, 9, 128, 6, 180, 453, 403}, - {13, 141, 4, 23, 5, 2, 115, 217, 202, 51, 180, 137, 269, 352, 77, 1, 317, 3, 21, 318, 0, 15, 9, 64, 10, 197, 11, 341, 33, 515, 752, 7}, - {165, 125, 197, 13, 391, 21, 23, 558, 48, 380, 97, 120, 298, 33, 14, 426, 66, 115, 32, 386, 900, 180, 6, 98, 357, 237, 326, 509, 51, 278, 221, 457}, - {120, 82, 15, 260, 515, 1, 351, 77, 450, 700, 13, 21, 141, 23, 753, 202, 217, 93, 110, 33, 51, 854, 5, 128, 326, 102, 137, 180, 817, 48, 269, 352}, - {23, 13, 15, 51, 515, 700, 961, 753, 0, 457, 1, 2, 4, 115, 10, 453, 569, 5, 33, 165, 11, 719, 14, 40, 64, 197, 3, 21, 474, 629, 38, 401}, - {264, 166, 39, 30, 9, 100, 435, 254, 93, 921, 190, 363, 1, 625, 411, 382, 897, 656, 203, 478, 404, 812, 438, 110, 473, 88, 18, 691, 156, 141, 274, 272}, - {9, 0, 252, 100, 166, 39, 101, 265, 364, 68, 88, 329, 520, 18, 419, 676, 118, 167, 404, 604, 16, 1, 21, 30, 212, 158, 553, 49, 382, 274, 48, 13}, - {15, 515, 700, 753, 4, 11, 141, 5, 3, 13, 202, 1, 180, 21, 2, 165, 269, 23, 40, 64, 0, 318, 12, 32, 128, 51, 77, 117, 523, 197, 120, 457}, - {24, 1, 2, 69, 35, 16, 67, 18, 14, 50, 0, 46, 68, 9, 38, 7, 133, 71, 83, 149, 28, 108, 189, 218, 65, 114, 238, 29, 75, 54, 5, 96}, - {90, 289, 214, 64, 874, 13, 77, 712, 66, 751, 4, 23, 51, 192, 32, 0, 202, 194, 312, 177, 33, 65, 234, 104, 875, 288, 59, 5, 835, 416, 102, 95}, - {0, 9, 49, 127, 98, 31, 301, 28, 371, 159, 1, 395, 512, 737, 158, 761, 916, 623, 16, 44, 242, 39, 170, 18, 293, 105, 24, 272, 101, 22, 23, 385}, - {17, 62, 136, 214, 123, 129, 32, 292, 119, 209, 710, 106, 141, 162, 128, 64, 45, 4, 77, 249, 11, 618, 211, 3, 207, 130, 519, 183, 38, 177, 21, 269}, - {5, 107, 581, 356, 279, 32, 441, 362, 493, 660, 13, 298, 0, 534, 49, 147, 21, 22, 132, 121, 97, 423, 7, 590, 259, 683, 14, 786, 126, 508, 60, 246}, - {51, 13, 15, 730, 453, 23, 515, 719, 386, 457, 12, 700, 403, 475, 899, 1, 6, 523, 753, 421, 99, 401, 165, 33, 2, 19, 361, 5, 0, 670, 120, 27}, - {49, 28, 9, 159, 272, 22, 254, 131, 158, 327, 95, 105, 0, 39, 35, 168, 347, 286, 374, 55, 65, 627, 424, 912, 68, 578, 1, 24, 239, 175, 688, 169}, - {15, 515, 700, 33, 753, 4, 77, 141, 341, 317, 1, 10, 13, 180, 102, 22, 40, 117, 115, 365, 5, 901, 23, 197, 134, 11, 217, 351, 64, 82, 21, 137}, - {134, 15, 13, 515, 23, 700, 12, 753, 51, 474, 37, 961, 197, 10, 457, 569, 4, 0, 99, 2, 115, 38, 165, 153, 94, 3, 139, 11, 1, 82, 33, 5}, - {7, 2, 20, 58, 5, 14, 128, 66, 6, 29, 32, 43, 21, 52, 16, 38, 631, 61, 74, 97, 46, 135, 113, 25, 202, 192, 13, 0, 884, 45, 112, 87}, - {77, 13, 33, 202, 23, 128, 102, 4, 141, 342, 117, 0, 269, 318, 134, 22, 11, 21, 32, 153, 403, 291, 49, 64, 137, 51, 40, 15, 494, 5, 196, 98}, - {2, 1, 14, 6, 46, 38, 29, 65, 5, 36, 67, 0, 103, 7, 22, 86, 133, 50, 108, 208, 52, 83, 24, 323, 283, 69, 28, 18, 10, 25, 23, 75}, - {15, 515, 700, 753, 1, 5, 4, 2, 3, 13, 0, 11, 180, 341, 12, 33, 10, 197, 134, 365, 77, 23, 21, 901, 6, 117, 165, 7, 37, 32, 17, 102}, - {203, 268, 206, 93, 417, 940, 31, 8, 120, 137, 44, 499, 959, 473, 202, 692, 728, 559, 0, 260, 10, 326, 141, 564, 817, 127, 341, 1, 450, 22, 110, 23}, - {15, 82, 515, 120, 700, 0, 10, 753, 33, 8, 64, 165, 110, 31, 260, 93, 13, 197, 23, 22, 40, 4, 351, 44, 77, 9, 11, 153, 102, 51, 1, 196}, - {60, 0, 16, 7, 14, 43, 20, 71, 28, 10, 2, 22, 154, 18, 13, 24, 92, 1, 51, 576, 35, 615, 805, 925, 68, 126, 124, 149, 97, 64, 23, 55}, - {19, 6, 26, 80, 5, 84, 27, 17, 25, 2, 504, 129, 45, 240, 56, 123, 4, 119, 618, 1, 76, 106, 64, 51, 14, 3, 128, 65, 32, 710, 0, 42}, - {15, 515, 700, 753, 13, 4, 77, 23, 33, 51, 0, 5, 8, 10, 11, 31, 44, 1, 82, 22, 202, 64, 110, 102, 93, 21, 291, 40, 141, 180, 9, 49}, - {195, 98, 271, 223, 132, 167, 146, 407, 1, 360, 121, 834, 393, 591, 212, 199, 293, 259, 522, 107, 354, 147, 156, 191, 807, 590, 48, 18, 125, 16, 765, 541}, - {128, 202, 77, 210, 402, 318, 33, 102, 6, 40, 403, 29, 342, 269, 196, 757, 99, 139, 2, 111, 42, 4, 494, 117, 275, 300, 13, 12, 678, 0, 177, 122}, - {13, 33, 23, 40, 51, 102, 4, 117, 77, 64, 134, 0, 128, 153, 202, 196, 453, 11, 15, 12, 1, 22, 403, 141, 59, 14, 10, 475, 515, 65, 700, 95}, - {7, 16, 14, 24, 18, 2, 28, 0, 92, 71, 1, 22, 6, 35, 60, 20, 168, 10, 154, 118, 5, 302, 124, 69, 97, 109, 703, 158, 420, 12, 149, 66}, - {15, 1, 515, 23, 0, 13, 700, 2, 51, 753, 180, 5, 120, 165, 197, 21, 115, 4, 33, 9, 141, 7, 12, 6, 3, 457, 386, 202, 260, 523, 8, 31}, - {60, 107, 121, 132, 146, 126, 199, 279, 150, 92, 16, 649, 441, 35, 955, 7, 21, 0, 423, 5, 18, 195, 598, 298, 493, 356, 32, 653, 22, 362, 953, 10}, - {31, 44, 98, 276, 284, 299, 116, 935, 9, 201, 0, 131, 39, 127, 144, 662, 1, 137, 371, 492, 567, 489, 93, 254, 49, 268, 22, 28, 30, 293, 434, 737}, - {13, 15, 23, 515, 700, 0, 1, 51, 753, 4, 2, 10, 77, 202, 5, 115, 3, 165, 197, 457, 9, 12, 11, 961, 33, 120, 22, 141, 180, 7, 6, 40}, - {123, 162, 184, 257, 17, 183, 229, 130, 129, 3, 84, 136, 99, 152, 556, 383, 57, 497, 12, 205, 4, 62, 56, 452, 80, 266, 128, 14, 40, 119, 27, 106}, - {196, 33, 117, 40, 153, 23, 134, 13, 51, 102, 453, 0, 15, 475, 12, 14, 515, 2, 22, 700, 4, 21, 753, 64, 401, 670, 730, 1, 9, 11, 10, 99}, - {224, 219, 187, 131, 258, 385, 442, 871, 836, 31, 98, 908, 44, 574, 127, 944, 137, 839, 116, 36, 613, 1, 254, 39, 926, 160, 829, 96, 93, 371, 860, 827}, - {121, 195, 156, 132, 146, 360, 590, 407, 786, 522, 883, 591, 259, 929, 626, 941, 150, 687, 5, 55, 296, 379, 467, 178, 586, 465, 279, 21, 1, 13, 60, 354}, - {2, 1, 14, 29, 6, 5, 46, 52, 38, 19, 114, 75, 26, 65, 108, 96, 25, 50, 36, 70, 103, 309, 17, 236, 218, 74, 12, 86, 0, 3, 10, 112}, - {15, 515, 82, 700, 120, 753, 10, 0, 8, 197, 260, 165, 351, 64, 13, 110, 117, 93, 31, 1, 9, 33, 22, 23, 457, 44, 450, 77, 102, 898, 40, 49}, - {7, 66, 97, 2, 172, 74, 226, 52, 29, 135, 192, 232, 43, 324, 92, 5, 38, 20, 222, 14, 6, 568, 87, 107, 353, 620, 580, 16, 138, 174, 448, 32}, - {62, 129, 123, 162, 136, 249, 618, 183, 507, 57, 4, 152, 17, 59, 11, 184, 117, 77, 3, 128, 211, 41, 130, 205, 12, 40, 33, 106, 64, 229, 38, 313}, - {1, 13, 15, 2, 4, 515, 23, 0, 3, 115, 700, 5, 51, 77, 341, 141, 753, 180, 33, 217, 197, 202, 901, 6, 21, 165, 11, 365, 318, 317, 10, 102}, - {6, 26, 235, 19, 145, 47, 112, 78, 64, 27, 453, 95, 29, 444, 25, 624, 85, 108, 648, 70, 32, 130, 74, 42, 711, 630, 632, 138, 65, 122, 113, 730}, - {23, 51, 12, 15, 13, 99, 515, 153, 117, 10, 700, 37, 120, 82, 165, 2, 753, 64, 128, 0, 403, 3, 5, 1, 134, 197, 453, 31, 202, 457, 110, 21}, - {16, 24, 18, 71, 64, 35, 92, 7, 246, 146, 9, 108, 60, 118, 199, 5, 140, 2, 267, 0, 230, 830, 32, 133, 1, 68, 50, 330, 247, 563, 36, 12}, - {15, 515, 700, 753, 0, 1, 13, 2, 23, 3, 4, 217, 51, 5, 115, 8, 9, 180, 341, 10, 7, 6, 317, 77, 33, 372, 901, 197, 365, 11, 120, 165}, - {234, 639, 178, 202, 77, 142, 5, 455, 450, 49, 416, 0, 147, 427, 198, 21, 315, 329, 13, 318, 325, 557, 120, 344, 113, 259, 22, 128, 61, 105, 23, 494}, - {1, 31, 36, 44, 141, 180, 55, 2, 64, 22, 98, 116, 13, 352, 0, 115, 10, 127, 5, 164, 253, 498, 237, 165, 341, 197, 4, 86, 15, 170, 125, 23}, - {15, 120, 13, 141, 23, 260, 217, 515, 1, 77, 51, 110, 180, 700, 317, 82, 269, 137, 115, 202, 21, 753, 64, 5, 351, 291, 0, 450, 352, 93, 36, 326}, - {26, 6, 112, 396, 19, 145, 25, 122, 648, 287, 42, 74, 624, 222, 416, 45, 138, 66, 644, 151, 113, 651, 29, 573, 64, 280, 445, 27, 525, 85, 70, 58}, - {156, 360, 5, 146, 121, 21, 271, 522, 354, 132, 49, 13, 18, 195, 16, 340, 60, 591, 446, 586, 727, 0, 107, 407, 167, 48, 1, 463, 199, 566, 32, 23}, - {5, 61, 49, 147, 178, 612, 660, 120, 21, 182, 23, 427, 259, 683, 33, 4, 77, 70, 13, 3, 376, 98, 64, 0, 481, 344, 48, 595, 291, 263, 141, 51}, - {89, 79, 468, 179, 358, 205, 94, 405, 115, 498, 72, 180, 365, 431, 37, 111, 341, 734, 188, 317, 482, 217, 11, 4, 245, 152, 413, 216, 12, 474, 490, 752}, - {24, 16, 35, 68, 18, 71, 7, 92, 0, 108, 9, 14, 118, 101, 336, 175, 375, 302, 28, 124, 154, 55, 149, 60, 398, 1, 65, 2, 140, 273, 345, 230}, - {51, 730, 421, 801, 453, 386, 23, 523, 13, 475, 719, 401, 670, 365, 899, 403, 115, 457, 758, 165, 33, 494, 450, 6, 423, 805, 629, 56, 569, 514, 958, 388}, - {113, 45, 6, 311, 29, 2, 151, 614, 145, 491, 112, 80, 5, 27, 61, 74, 315, 66, 209, 631, 19, 25, 58, 17, 73, 26, 1, 243, 70, 64, 611, 287}, - {4, 339, 188, 471, 11, 59, 79, 12, 377, 94, 99, 33, 77, 102, 51, 111, 37, 152, 13, 961, 474, 542, 40, 342, 3, 23, 128, 403, 202, 177, 184, 57}, - {15, 4, 515, 11, 700, 33, 82, 40, 0, 120, 753, 10, 8, 110, 13, 93, 23, 165, 77, 260, 64, 31, 22, 51, 44, 102, 351, 1, 125, 9, 197, 21}, - {16, 24, 18, 0, 35, 68, 28, 71, 124, 118, 60, 7, 9, 55, 14, 92, 109, 101, 419, 175, 22, 252, 154, 375, 149, 302, 158, 346, 2, 49, 1, 126}, - {17, 45, 227, 21, 106, 3, 2, 243, 209, 5, 48, 32, 221, 62, 207, 50, 29, 186, 290, 270, 263, 52, 14, 496, 400, 119, 46, 255, 54, 430, 38, 721}, - {340, 354, 586, 658, 156, 195, 698, 668, 1, 296, 9, 18, 883, 363, 447, 379, 303, 98, 411, 13, 31, 163, 51, 5, 371, 48, 919, 846, 121, 21, 360, 70}, - {277, 153, 111, 12, 23, 51, 474, 99, 38, 37, 139, 117, 41, 457, 79, 453, 542, 13, 11, 33, 134, 157, 629, 188, 961, 14, 196, 401, 102, 569, 15, 94}, - {0, 18, 16, 159, 49, 24, 9, 105, 35, 68, 7, 28, 22, 1, 60, 344, 55, 101, 109, 2, 14, 158, 13, 23, 71, 118, 455, 286, 272, 424, 5, 327}, - {0, 105, 9, 49, 16, 18, 158, 28, 518, 24, 101, 320, 1, 68, 170, 301, 272, 127, 7, 286, 35, 890, 109, 39, 159, 98, 21, 344, 31, 55, 371, 23}, - {141, 1, 180, 15, 13, 2, 365, 217, 515, 352, 317, 115, 341, 0, 4, 5, 269, 700, 23, 21, 3, 752, 197, 77, 753, 51, 31, 901, 10, 202, 8, 64}, - {4, 23, 51, 33, 19, 17, 102, 153, 485, 880, 40, 403, 196, 26, 300, 453, 27, 117, 78, 0, 12, 200, 47, 5, 11, 14, 342, 99, 53, 77, 475, 2}, - {62, 184, 56, 440, 130, 229, 183, 3, 556, 152, 99, 162, 12, 266, 17, 548, 136, 57, 305, 161, 123, 14, 452, 4, 383, 403, 257, 34, 40, 84, 33, 139}, - {13, 23, 77, 141, 64, 202, 33, 51, 269, 115, 0, 102, 21, 4, 217, 128, 5, 32, 318, 137, 291, 9, 15, 2, 180, 10, 3, 317, 177, 515, 7, 6}, - {1, 22, 36, 105, 170, 0, 86, 2, 31, 28, 239, 64, 55, 5, 10, 98, 9, 44, 127, 95, 654, 67, 301, 143, 13, 12, 49, 23, 320, 141, 83, 21}, - {15, 515, 700, 753, 0, 1, 13, 2, 23, 901, 5, 8, 51, 82, 9, 180, 457, 4, 7, 12, 3, 6, 10, 120, 341, 141, 22, 898, 197, 351, 115, 260}, - {1, 39, 274, 98, 100, 265, 190, 30, 438, 310, 166, 223, 88, 96, 909, 31, 264, 625, 530, 9, 382, 812, 21, 252, 593, 0, 254, 539, 44, 131, 23, 778}, - {18, 212, 167, 118, 363, 1, 447, 411, 146, 60, 271, 16, 781, 121, 647, 9, 621, 562, 21, 478, 664, 68, 815, 5, 354, 98, 48, 101, 24, 446, 777, 463}, - {24, 28, 22, 0, 7, 1, 2, 16, 14, 65, 35, 49, 158, 95, 109, 159, 55, 105, 10, 18, 124, 9, 67, 5, 239, 149, 12, 289, 108, 68, 21, 424}, - {105, 22, 131, 272, 286, 98, 55, 239, 1, 31, 320, 9, 127, 327, 36, 185, 28, 374, 86, 219, 0, 64, 187, 44, 578, 164, 224, 913, 535, 115, 601, 13}, - {22, 31, 28, 301, 127, 98, 44, 0, 105, 1, 512, 395, 9, 293, 109, 299, 95, 338, 239, 125, 242, 116, 36, 320, 55, 841, 900, 685, 599, 23, 13, 763}, - {2, 1, 58, 29, 5, 14, 52, 46, 186, 334, 45, 155, 151, 50, 400, 75, 38, 69, 502, 61, 48, 227, 223, 7, 163, 17, 262, 67, 549, 21, 70, 113}, - {7, 107, 135, 232, 97, 14, 2, 92, 66, 16, 172, 192, 278, 387, 298, 356, 38, 35, 448, 52, 46, 43, 60, 29, 20, 126, 324, 526, 357, 359, 64, 5}, - {20, 43, 104, 426, 173, 7, 560, 414, 707, 784, 319, 81, 0, 861, 422, 819, 38, 74, 715, 52, 376, 97, 879, 32, 330, 22, 49, 64, 66, 95, 192, 526}, - {104, 74, 636, 66, 204, 0, 355, 81, 222, 25, 29, 319, 145, 784, 20, 65, 90, 4, 174, 194, 7, 64, 6, 746, 138, 173, 750, 715, 91, 43, 192, 32}, - {0, 9, 101, 35, 68, 39, 65, 28, 252, 124, 67, 154, 364, 336, 100, 166, 30, 1, 289, 55, 149, 346, 16, 114, 158, 88, 439, 24, 429, 22, 570, 194}, - {57, 14, 4, 231, 236, 585, 176, 59, 369, 23, 361, 13, 719, 51, 300, 342, 12, 457, 56, 3, 62, 38, 202, 401, 34, 46, 2, 322, 11, 215, 210, 507}, - {1, 2, 15, 3, 141, 0, 515, 5, 33, 700, 13, 64, 77, 180, 6, 128, 753, 10, 4, 269, 102, 202, 11, 7, 134, 197, 352, 120, 117, 318, 12, 291}, - {5, 1, 21, 202, 13, 32, 48, 23, 0, 61, 259, 22, 494, 120, 70, 49, 51, 18, 137, 128, 465, 12, 178, 115, 2, 453, 403, 141, 58, 3, 90, 450}, - {141, 205, 4, 72, 59, 79, 245, 11, 352, 94, 152, 76, 247, 216, 21, 188, 452, 217, 497, 12, 89, 37, 111, 339, 588, 77, 64, 875, 864, 115, 358, 464}, - {15, 515, 700, 753, 0, 1, 2, 13, 5, 4, 23, 3, 8, 341, 365, 51, 115, 10, 120, 457, 6, 141, 77, 197, 31, 7, 165, 9, 202, 450, 961, 260}, - {5, 2, 50, 14, 58, 38, 171, 46, 29, 1, 45, 186, 17, 52, 155, 218, 48, 281, 61, 487, 54, 36, 67, 21, 328, 334, 151, 227, 760, 114, 400, 133}, - {457, 120, 70, 125, 318, 64, 23, 48, 795, 291, 202, 761, 751, 415, 77, 846, 269, 758, 21, 237, 96, 260, 391, 165, 87, 1, 128, 5, 221, 13, 137, 763}, - {13, 23, 51, 33, 4, 40, 117, 102, 453, 64, 153, 196, 0, 77, 15, 11, 12, 475, 1, 65, 134, 10, 515, 22, 21, 14, 700, 59, 403, 141, 2, 753}, - {229, 152, 57, 266, 452, 381, 432, 12, 313, 184, 99, 471, 17, 4, 62, 339, 157, 3, 129, 59, 128, 11, 369, 37, 77, 38, 40, 123, 5, 497, 188, 257}, - {49, 28, 109, 22, 159, 9, 272, 95, 105, 131, 55, 35, 254, 168, 39, 327, 169, 0, 1, 286, 175, 374, 347, 158, 420, 67, 36, 194, 312, 424, 627, 346}, - {5, 2, 61, 29, 45, 58, 80, 311, 1, 17, 209, 227, 52, 243, 106, 869, 454, 151, 592, 496, 48, 334, 14, 155, 6, 186, 46, 171, 75, 21, 255, 667}, - {244, 44, 110, 141, 260, 30, 269, 352, 839, 131, 574, 228, 373, 276, 1, 406, 219, 717, 217, 137, 253, 224, 120, 93, 36, 31, 567, 116, 661, 187, 341, 88}, - {12, 99, 79, 139, 11, 453, 196, 51, 277, 474, 111, 23, 542, 37, 94, 188, 33, 13, 401, 775, 40, 961, 313, 102, 4, 339, 153, 485, 629, 134, 300, 431}, - {16, 35, 9, 0, 68, 24, 149, 69, 67, 18, 1, 114, 65, 230, 71, 7, 103, 133, 50, 167, 212, 118, 101, 191, 140, 64, 399, 28, 124, 283, 55, 565}, - {88, 30, 274, 435, 131, 613, 190, 100, 93, 829, 166, 1, 187, 795, 530, 127, 382, 957, 960, 160, 31, 137, 466, 264, 39, 800, 406, 254, 28, 473, 521, 219}, - {167, 16, 18, 118, 212, 24, 60, 71, 101, 68, 191, 9, 375, 411, 363, 35, 0, 1, 589, 199, 302, 21, 447, 55, 146, 126, 92, 271, 647, 121, 562, 48}, - {64, 141, 86, 177, 77, 128, 147, 597, 304, 95, 269, 102, 275, 4, 352, 49, 120, 5, 372, 194, 465, 13, 588, 237, 947, 216, 202, 180, 612, 751, 107, 534}, - {18, 65, 90, 403, 523, 289, 240, 214, 194, 102, 701, 475, 202, 217, 283, 862, 389, 51, 33, 0, 494, 421, 453, 817, 84, 64, 847, 899, 352, 13, 23, 437}, - {13, 51, 23, 202, 5, 12, 21, 128, 15, 115, 0, 1, 141, 120, 64, 32, 4, 2, 515, 403, 165, 457, 3, 10, 700, 99, 453, 318, 719, 450, 308, 401}, - {98, 223, 393, 31, 1, 271, 834, 791, 167, 44, 202, 64, 93, 697, 5, 116, 77, 125, 450, 446, 212, 18, 541, 293, 51, 120, 195, 132, 284, 13, 807, 765}, - {15, 515, 700, 753, 4, 11, 23, 13, 40, 51, 82, 165, 0, 110, 93, 33, 141, 64, 120, 5, 10, 77, 3, 102, 180, 32, 202, 125, 8, 197, 31, 21}, - {15, 515, 700, 753, 0, 1, 13, 2, 901, 23, 5, 341, 3, 51, 82, 8, 4, 180, 961, 9, 115, 10, 12, 6, 898, 7, 351, 141, 134, 22, 31, 120}, - {234, 416, 77, 5, 315, 639, 325, 202, 147, 198, 113, 49, 450, 61, 455, 142, 0, 21, 22, 342, 329, 494, 178, 58, 102, 427, 318, 230, 13, 120, 43, 470}, - {60, 146, 16, 18, 156, 126, 121, 271, 199, 360, 132, 24, 167, 0, 640, 10, 71, 522, 21, 92, 5, 340, 107, 354, 118, 150, 22, 195, 446, 35, 28, 212}, - {4, 361, 11, 14, 56, 368, 377, 161, 27, 12, 300, 77, 59, 200, 17, 554, 202, 33, 40, 494, 495, 21, 210, 80, 757, 25, 128, 23, 19, 38, 444, 53}, - {141, 82, 217, 351, 15, 352, 120, 1, 180, 260, 515, 64, 854, 36, 700, 317, 752, 372, 13, 269, 77, 753, 922, 21, 349, 23, 202, 110, 93, 137, 51, 373}, - {15, 515, 700, 753, 77, 13, 0, 1, 23, 33, 102, 2, 51, 4, 3, 5, 291, 217, 10, 9, 450, 120, 341, 7, 317, 6, 11, 117, 115, 8, 260, 180}, - {15, 515, 120, 13, 700, 23, 77, 141, 1, 260, 0, 753, 180, 51, 137, 202, 115, 365, 110, 291, 217, 5, 128, 9, 21, 341, 197, 269, 2, 450, 317, 165}, - {174, 6, 348, 85, 138, 74, 280, 204, 66, 233, 192, 355, 289, 65, 81, 580, 636, 353, 25, 91, 104, 343, 673, 214, 64, 95, 42, 712, 792, 32, 194, 90}, - {152, 497, 452, 59, 4, 216, 11, 79, 94, 77, 128, 188, 269, 339, 588, 33, 76, 529, 318, 32, 141, 471, 12, 202, 111, 21, 5, 51, 37, 90, 72, 177}, - {417, 499, 10, 141, 253, 244, 110, 559, 8, 564, 180, 260, 728, 120, 352, 638, 642, 341, 951, 206, 143, 752, 901, 93, 137, 661, 922, 373, 44, 31, 811, 197}, - {13, 77, 23, 33, 4, 51, 0, 102, 128, 59, 141, 40, 64, 115, 177, 10, 137, 22, 202, 2, 7, 11, 90, 1, 117, 180, 269, 14, 49, 6, 134, 3}, - {1, 2, 22, 0, 36, 5, 67, 50, 14, 28, 12, 86, 38, 46, 83, 168, 194, 65, 103, 114, 49, 7, 10, 95, 21, 69, 23, 24, 128, 51, 55, 13}, - {17, 106, 119, 207, 255, 306, 742, 378, 84, 62, 136, 45, 3, 5, 240, 80, 61, 56, 209, 383, 311, 790, 655, 32, 2, 440, 76, 151, 58, 29, 179, 263}, - {3, 128, 1, 141, 2, 202, 33, 5, 64, 15, 0, 515, 102, 13, 269, 10, 700, 180, 134, 51, 120, 6, 77, 318, 23, 137, 17, 117, 753, 197, 82, 153}, - {514, 38, 377, 328, 11, 57, 41, 248, 880, 266, 556, 4, 152, 361, 471, 757, 485, 403, 305, 102, 3, 211, 313, 99, 457, 130, 12, 14, 157, 40, 23, 54}, - {68, 0, 167, 101, 9, 118, 264, 520, 16, 18, 21, 478, 562, 1, 124, 212, 100, 936, 664, 777, 191, 88, 806, 154, 48, 24, 759, 604, 35, 252, 265, 65}, - {230, 689, 699, 213, 466, 352, 217, 831, 30, 443, 418, 144, 854, 201, 840, 855, 1, 251, 203, 317, 530, 957, 96, 93, 822, 539, 36, 752, 351, 137, 83, 800}, - {33, 77, 102, 117, 15, 82, 13, 134, 23, 64, 0, 515, 120, 153, 51, 4, 40, 128, 700, 260, 202, 141, 196, 22, 753, 11, 351, 10, 1, 326, 95, 269}, - {11, 40, 33, 51, 117, 13, 542, 328, 14, 134, 38, 153, 23, 12, 485, 231, 102, 54, 775, 37, 3, 377, 111, 139, 211, 4, 457, 403, 369, 475, 99, 719}, - {33, 64, 77, 128, 141, 2, 1, 202, 102, 13, 23, 117, 0, 15, 3, 153, 51, 134, 10, 40, 6, 5, 515, 269, 137, 180, 318, 165, 700, 7, 196, 753}, - {15, 515, 700, 753, 4, 1, 5, 11, 13, 21, 33, 180, 93, 141, 64, 2, 23, 77, 82, 3, 0, 102, 32, 40, 352, 341, 10, 197, 98, 110, 117, 901}, - {1, 2, 14, 67, 50, 46, 38, 24, 103, 83, 0, 5, 36, 28, 29, 133, 114, 96, 65, 52, 18, 75, 54, 108, 22, 7, 238, 58, 160, 9, 361, 69}, - {258, 201, 276, 137, 160, 860, 116, 261, 295, 843, 567, 144, 131, 44, 187, 268, 943, 219, 284, 31, 202, 935, 141, 98, 662, 203, 127, 96, 36, 93, 224, 1}, - {7, 2, 14, 16, 46, 87, 75, 52, 92, 278, 29, 38, 140, 70, 1, 5, 35, 294, 24, 262, 135, 69, 171, 172, 58, 409, 112, 60, 50, 66, 97, 12}, - {13, 23, 0, 2, 51, 1, 33, 4, 115, 10, 15, 141, 77, 3, 5, 180, 217, 515, 9, 7, 64, 11, 700, 6, 102, 40, 197, 22, 317, 753, 165, 202}, - {74, 145, 6, 66, 25, 204, 42, 29, 222, 337, 138, 26, 7, 525, 192, 174, 746, 287, 544, 135, 415, 2, 609, 632, 112, 64, 87, 0, 85, 45, 712, 396}, - {77, 33, 102, 15, 217, 13, 23, 141, 202, 515, 51, 700, 291, 4, 269, 753, 317, 180, 21, 64, 318, 115, 128, 0, 275, 2, 352, 196, 3, 5, 137, 11}, - {187, 219, 258, 871, 44, 442, 160, 574, 137, 224, 908, 116, 839, 131, 36, 926, 276, 201, 93, 228, 202, 860, 31, 613, 144, 531, 406, 1, 902, 30, 190, 318}, - {1, 372, 141, 5, 21, 77, 225, 744, 96, 30, 23, 349, 13, 291, 269, 284, 69, 442, 459, 144, 303, 839, 217, 622, 160, 330, 260, 48, 120, 410, 189, 352}, - {66, 222, 2, 74, 29, 87, 135, 6, 7, 145, 52, 25, 294, 337, 226, 172, 138, 331, 42, 70, 97, 112, 26, 1, 632, 192, 43, 5, 415, 609, 461, 353}, - {45, 17, 106, 209, 5, 2, 21, 29, 48, 207, 3, 186, 243, 155, 255, 263, 454, 119, 400, 496, 270, 14, 290, 62, 425, 1, 171, 32, 659, 52, 38, 56}, - {93, 88, 141, 120, 30, 213, 260, 373, 100, 717, 459, 82, 110, 1, 166, 450, 180, 321, 217, 372, 36, 269, 131, 225, 22, 352, 326, 466, 473, 187, 244, 410}, - {266, 57, 152, 381, 313, 471, 12, 229, 99, 369, 339, 62, 157, 3, 4, 37, 77, 38, 188, 17, 11, 162, 40, 184, 129, 59, 475, 775, 128, 452, 403, 453}, - {217, 352, 317, 141, 752, 15, 180, 515, 372, 365, 700, 341, 753, 349, 77, 21, 291, 1, 115, 244, 64, 120, 13, 98, 269, 82, 5, 498, 864, 351, 23, 144}, - {14, 514, 369, 102, 403, 377, 51, 719, 880, 153, 23, 13, 457, 11, 485, 4, 401, 12, 328, 453, 33, 40, 117, 57, 629, 38, 730, 236, 134, 670, 361, 961}, - {107, 7, 172, 14, 92, 135, 2, 359, 60, 314, 46, 16, 126, 278, 232, 150, 279, 32, 38, 392, 298, 5, 35, 97, 24, 192, 259, 288, 330, 52, 356, 312}, - {0, 4, 25, 13, 59, 90, 65, 23, 26, 19, 18, 12, 5, 216, 91, 51, 389, 33, 77, 11, 22, 85, 27, 81, 21, 177, 746, 45, 42, 194, 37, 123}, - {5, 49, 315, 202, 416, 77, 455, 639, 450, 21, 197, 137, 350, 13, 408, 0, 329, 318, 494, 344, 61, 402, 64, 509, 347, 120, 113, 48, 95, 713, 308, 401}, - {130, 47, 381, 390, 59, 90, 200, 214, 289, 6, 65, 472, 29, 64, 874, 648, 50, 751, 624, 26, 52, 32, 4, 194, 875, 714, 85, 249, 247, 33, 881, 19}, - {51, 23, 453, 13, 719, 12, 457, 165, 37, 730, 99, 4, 386, 197, 401, 17, 11, 2, 3, 15, 5, 961, 475, 6, 515, 64, 54, 700, 32, 115, 0, 403}, - {15, 515, 1, 13, 700, 2, 23, 0, 753, 5, 3, 180, 51, 4, 165, 12, 141, 21, 197, 457, 7, 115, 6, 9, 352, 10, 120, 202, 8, 341, 11, 77}, - {0, 9, 1, 67, 35, 28, 68, 16, 24, 65, 18, 69, 50, 114, 103, 12, 22, 13, 5, 101, 2, 96, 23, 83, 149, 21, 39, 55, 7, 175, 433, 124}, - {28, 105, 22, 0, 1, 320, 170, 9, 49, 301, 109, 95, 127, 31, 98, 55, 65, 35, 2, 24, 168, 159, 36, 713, 16, 740, 13, 338, 21, 44, 512, 23}, - {13, 77, 4, 51, 23, 33, 102, 202, 128, 59, 40, 0, 64, 141, 117, 403, 115, 11, 15, 318, 153, 269, 22, 515, 475, 134, 10, 494, 177, 1, 90, 210}, - {13, 23, 0, 51, 77, 33, 2, 141, 4, 10, 1, 64, 115, 102, 3, 6, 22, 15, 217, 11, 180, 7, 40, 515, 165, 202, 177, 9, 269, 128, 700, 5}, - {456, 116, 492, 8, 949, 268, 867, 391, 203, 51, 499, 13, 719, 386, 31, 791, 457, 918, 125, 10, 23, 93, 479, 685, 417, 0, 22, 338, 506, 551, 870, 730}, - {17, 237, 45, 180, 106, 62, 32, 64, 115, 41, 136, 498, 255, 21, 197, 129, 241, 13, 3, 227, 23, 352, 165, 752, 350, 365, 449, 155, 4, 546, 476, 38}, - {1, 15, 180, 515, 0, 2, 341, 700, 901, 352, 4, 141, 13, 3, 752, 5, 753, 217, 317, 115, 365, 23, 197, 21, 51, 165, 31, 6, 269, 202, 77, 7}, - {205, 141, 216, 269, 497, 4, 588, 76, 59, 152, 128, 452, 79, 77, 875, 11, 72, 94, 188, 217, 352, 12, 247, 37, 90, 64, 32, 1, 474, 23, 947, 372}, - {64, 247, 217, 237, 317, 180, 752, 115, 349, 141, 498, 13, 437, 304, 23, 372, 352, 164, 579, 291, 33, 864, 177, 197, 0, 490, 72, 10, 482, 77, 269, 51}, - {2, 1, 0, 13, 15, 141, 3, 77, 5, 515, 64, 33, 23, 180, 6, 700, 4, 117, 217, 7, 10, 11, 102, 165, 753, 197, 115, 134, 40, 352, 12, 269}, - {11, 40, 38, 328, 33, 542, 12, 313, 41, 339, 23, 157, 377, 117, 369, 51, 471, 99, 775, 485, 13, 305, 457, 57, 14, 475, 37, 248, 4, 54, 188, 719}, - {33, 77, 102, 40, 13, 23, 0, 51, 4, 128, 64, 202, 117, 141, 22, 196, 153, 10, 134, 15, 59, 269, 1, 137, 65, 11, 403, 318, 453, 86, 515, 177}, - {472, 80, 34, 250, 495, 161, 17, 14, 469, 176, 128, 4, 389, 106, 283, 436, 216, 527, 3, 297, 483, 177, 53, 56, 231, 194, 119, 84, 719, 57, 255, 59}, - {317, 352, 180, 141, 217, 752, 115, 341, 365, 244, 1, 269, 202, 901, 253, 15, 21, 498, 372, 4, 137, 515, 13, 2, 700, 318, 5, 197, 23, 143, 753, 349}, - {9, 39, 101, 18, 265, 100, 333, 520, 252, 16, 0, 329, 593, 1, 553, 364, 68, 167, 310, 30, 121, 254, 118, 158, 363, 166, 60, 604, 272, 24, 286, 404}, - {15, 515, 1, 180, 700, 901, 0, 2, 753, 341, 752, 4, 3, 13, 115, 365, 317, 5, 23, 197, 141, 217, 165, 352, 6, 22, 36, 9, 137, 51, 7, 10}, - {131, 39, 9, 829, 166, 613, 578, 827, 1, 30, 716, 254, 100, 98, 31, 224, 0, 406, 228, 310, 616, 219, 44, 846, 127, 190, 938, 96, 265, 371, 856, 438}, - {17, 64, 62, 106, 141, 751, 136, 292, 32, 129, 352, 41, 38, 476, 86, 128, 214, 237, 5, 177, 123, 209, 217, 45, 269, 954, 162, 710, 180, 3, 90, 4}, - {25, 42, 235, 65, 650, 736, 605, 6, 630, 85, 123, 343, 233, 256, 26, 122, 63, 389, 141, 249, 416, 444, 368, 194, 19, 108, 138, 174, 90, 0, 544, 511}, - {184, 229, 152, 57, 266, 432, 497, 452, 17, 381, 619, 257, 313, 12, 4, 205, 59, 3, 99, 471, 157, 128, 5, 129, 339, 369, 77, 11, 32, 45, 202, 2}, - {137, 202, 160, 860, 141, 30, 93, 567, 36, 276, 295, 261, 131, 39, 9, 964, 201, 843, 1, 98, 800, 318, 116, 22, 943, 187, 10, 219, 206, 44, 269, 535}, - {0, 493, 125, 64, 49, 9, 279, 10, 35, 18, 93, 55, 293, 31, 14, 13, 194, 165, 325, 48, 22, 132, 21, 107, 98, 389, 44, 581, 342, 259, 174, 137}, - {15, 515, 700, 753, 4, 33, 13, 77, 23, 5, 51, 32, 102, 40, 93, 11, 349, 141, 21, 8, 82, 202, 64, 31, 110, 10, 117, 0, 1, 44, 3, 318}, - {110, 253, 854, 811, 352, 141, 244, 951, 180, 642, 661, 384, 498, 143, 752, 317, - 911, 10, 269, 206, 559, 351, 261, 120, 902, 533, 922, 959, 365, 160, 332, 217}, - {2, 29, 70, 1, 75, 52, 6, 220, 26, 112, 145, 331, 74, 163, 19, 69, 38, 324, 46, 58, 14, 5, 25, 21, 278, 223, 50, 307, 66, 7, 67, 409}, - {13, 23, 77, 33, 51, 4, 64, 141, 115, 102, 0, 2, 128, 177, 40, 11, 202, 10, 6, 180, 7, 15, 269, 1, 32, 217, 59, 22, 291, 3, 137, 515}, - {340, 897, 691, 478, 658, 264, 914, 382, 100, 812, 363, 1, 724, 156, 166, 698, 88, 521, 39, 404, 682, 447, 296, 96, 303, 411, 30, 909, 9, 274, 656, 772}, - {9, 18, 310, 101, 265, 159, 326, 120, 105, 158, 33, 363, 77, 195, 51, 55, 13, 39, 354, 132, 23, 7, 28, 639, 16, 137, 98, 1, 252, 272, 709, 49}, - {57, 313, 471, 12, 99, 369, 157, 339, 266, 152, 38, 37, 475, 453, 328, 775, 11, 40, 59, 188, 77, 514, 401, 403, 342, 4, 139, 33, 377, 51, 229, 14}, - {16, 7, 24, 14, 35, 140, 60, 92, 18, 69, 71, 2, 189, 1, 46, 230, 108, 388, 150, 38, 21, 172, 278, 67, 246, 267, 50, 309, 236, 135, 451, 0}, - {206, 417, 93, 940, 959, 473, 499, 203, 8, 137, 559, 728, 31, 202, 44, 120, 450, 141, 10, 260, 116, 564, 22, 326, 269, 318, 268, 244, 0, 1, 253, 638}, - {15, 515, 700, 753, 1, 0, 13, 2, 23, 4, 3, 51, 5, 217, 7, 77, 341, 115, 8, 9, 10, 33, 6, 180, 317, 349, 291, 120, 11, 165, 457, 901}, - {1, 2, 5, 14, 48, 21, 290, 32, 50, 45, 38, 46, 263, 207, 155, 72, 76, 29, 17, 408, 425, 171, 89, 52, 7, 0, 292, 449, 3, 227, 513, 428}, - {121, 132, 354, 167, 271, 223, 146, 98, 18, 463, 1, 668, 446, 195, 407, 60, 212, 447, 781, 48, 360, 363, 411, 522, 156, 393, 807, 9, 21, 16, 293, 13}, - {131, 578, 105, 371, 219, 224, 716, 616, 187, 49, 9, 254, 737, 159, 385, 98, 258, 127, 272, 761, 0, 916, 623, 910, 28, 286, 39, 31, 22, 518, 924, 242}, - {302, 467, 97, 6, 273, 1, 24, 484, 124, 51, 36, 18, 2, 398, 453, 421, 523, 69, 7, 23, 13, 403, 386, 150, 66, 0, 298, 65, 426, 165, 22, 158}, - {30, 190, 530, 88, 1, 100, 778, 539, 625, 274, 382, 410, 96, 731, 960, 39, 795, 321, 9, 131, 264, 144, 840, 748, 44, 166, 669, 957, 36, 31, 435, 228}, - {141, 1, 2, 128, 64, 33, 15, 202, 3, 0, 180, 5, 13, 77, 515, 134, 269, 102, 197, 700, 10, 137, 318, 6, 120, 165, 753, 352, 4, 82, 23, 117}, - {44, 201, 567, 116, 131, 224, 295, 662, 489, 268, 219, 31, 434, 144, 187, 276, 110, 384, 93, 261, 699, 137, 36, 442, 120, 1, 613, 30, 228, 64, 141, 244}, - {12, 15, 51, 23, 515, 37, 99, 13, 700, 0, 10, 117, 753, 38, 165, 82, 134, 120, 11, 453, 197, 64, 115, 569, 1, 629, 401, 22, 457, 474, 110, 153}, - {7, 135, 2, 92, 172, 14, 66, 140, 38, 52, 97, 46, 29, 74, 16, 324, 278, 226, 6, 87, 1, 571, 262, 5, 357, 232, 35, 380, 69, 314, 24, 330}, - {125, 386, 23, 963, 949, 60, 51, 391, 165, 221, 13, 197, 118, 21, 719, 193, 541, 421, 517, 150, 393, 7, 401, 453, 308, 5, 791, 551, 326, 558, 48, 173}, - {6, 85, 42, 25, 138, 222, 174, 235, 280, 256, 525, 289, 26, 214, 64, 746, 90, 32, 544, 65, 204, 19, 66, 337, 355, 95, 348, 415, 74, 29, 5, 312}, - {1, 14, 5, 50, 2, 67, 24, 0, 46, 69, 48, 21, 58, 103, 16, 12, 18, 38, 54, 96, 83, 7, 502, 45, 36, 181, 35, 9, 430, 28, 10, 155}, - {811, 351, 642, 180, 951, 752, 110, 638, 253, 10, 82, 352, 197, 341, 365, 564, 499, 854, 873, 55, 9, 417, 282, 901, 244, 22, 559, 143, 206, 141, 28, 898}, - {23, 13, 51, 15, 12, 453, 403, 165, 4, 515, 115, 719, 475, 457, 700, 523, 2, 21, 0, 99, 202, 197, 14, 5, 386, 753, 128, 401, 37, 308, 33, 117}, - {120, 13, 23, 77, 141, 1, 15, 93, 217, 82, 260, 51, 137, 202, 110, 515, 21, 180, 165, 5, 128, 102, 64, 351, 291, 700, 269, 352, 326, 203, 177, 0}, - {1, 5, 0, 22, 12, 2, 36, 21, 10, 23, 86, 13, 28, 51, 9, 128, 48, 14, 32, 50, 7, 3, 96, 137, 54, 4, 202, 49, 37, 65, 208, 323}, - {219, 98, 23, 127, 301, 51, 258, 308, 170, 910, 13, 165, 22, 105, 293, 616, 125, 242, 276, 401, 201, 395, 964, 115, 55, 284, 31, 374, 327, 206, 512, 900}, - {64, 180, 80, 165, 5, 237, 2, 250, 34, 58, 297, 61, 197, 17, 22, 29, 186, 498, 231, 445, 247, 3, 752, 311, 95, 32, 483, 153, 27, 45, 115, 469}, - {13, 77, 23, 33, 0, 2, 1, 64, 141, 51, 102, 10, 15, 3, 115, 40, 180, 6, 515, 128, 7, 22, 269, 202, 4, 217, 700, 5, 177, 117, 14, 165}, - {15, 120, 51, 515, 13, 450, 23, 700, 202, 153, 196, 753, 260, 64, 128, 141, 730, 4, 326, 386, 21, 523, 33, 318, 5, 457, 95, 32, 403, 1, 77, 269}, - {2, 1, 5, 29, 32, 45, 207, 263, 14, 425, 58, 72, 76, 21, 7, 408, 48, 46, 52, 186, 17, 292, 38, 6, 61, 89, 476, 50, 155, 720, 119, 3}, - {15, 515, 700, 753, 4, 13, 11, 5, 1, 23, 33, 21, 3, 141, 32, 2, 40, 180, 117, 64, 269, 202, 102, 197, 0, 165, 120, 51, 341, 352, 153, 12}, - {76, 5, 214, 129, 2, 123, 45, 710, 17, 249, 618, 460, 179, 32, 1, 257, 205, 519, 90, 207, 245, 184, 162, 61, 769, 209, 292, 106, 6, 29, 14, 128}, - {1, 15, 23, 13, 120, 141, 51, 515, 202, 21, 700, 165, 0, 180, 137, 2, 5, 77, 128, 93, 753, 260, 269, 197, 326, 33, 110, 352, 82, 102, 318, 48}, - {7, 2, 135, 14, 29, 87, 66, 52, 97, 172, 70, 112, 5, 58, 46, 337, 92, 16, 20, 43, 1, 38, 232, 155, 74, 294, 6, 461, 409, 151, 262, 32}, - {574, 187, 384, 926, 860, 110, 258, 434, 269, 531, 141, 244, 160, 261, 253, 116, - 699, 959, 940, 717, 533, 36, 219, 31, 902, 661, 871, 295, 201, 352, 10, 260}, - {156, 354, 296, 1, 182, 586, 64, 379, 340, 937, 850, 698, 31, 48, 98, 44, 120, 18, 163, 23, 30, 658, 195, 125, 77, 284, 223, 291, 774, 481, 96, 39}, - {250, 80, 34, 472, 17, 495, 176, 469, 33, 194, 64, 483, 4, 297, 141, 14, 161, 27, 53, 667, 56, 833, 73, 527, 585, 231, 106, 51, 84, 814, 2, 59}, - {97, 7, 81, 140, 66, 92, 172, 192, 24, 298, 43, 6, 74, 69, 314, 426, 462, 14, 501, 16, 21, 508, 60, 189, 267, 232, 230, 104, 48, 20, 135, 330}, - {31, 44, 116, 144, 268, 393, 492, 434, 367, 489, 127, 98, 918, 0, 384, 9, 22, 206, 948, 105, 93, 203, 1, 456, 332, 940, 299, 28, 137, 49, 293, 125}, - {15, 128, 33, 3, 13, 51, 141, 1, 202, 64, 23, 2, 515, 120, 102, 0, 5, 82, 10, 700, 165, 197, 269, 153, 403, 110, 753, 137, 196, 318, 117, 12}, - {31, 98, 127, 9, 0, 105, 22, 28, 44, 512, 293, 395, 299, 1, 242, 49, 685, 763, 320, 599, 125, 116, 109, 276, 284, 95, 870, 159, 23, 456, 36, 900}, - {7, 24, 124, 1, 6, 97, 2, 69, 14, 18, 23, 92, 21, 67, 66, 16, 5, 484, 43, 20, 118, 65, 36, 22, 28, 0, 51, 140, 13, 71, 29, 150}, - {1, 64, 442, 303, 284, 349, 202, 141, 622, 67, 154, 447, 260, 44, 652, 429, 9, 335, 237, 919, 197, 98, 167, 33, 682, 269, 547, 77, 863, 411, 340, 201}, - {1, 15, 2, 141, 515, 0, 700, 13, 3, 180, 10, 753, 5, 64, 77, 33, 4, 6, 7, 197, 102, 269, 165, 23, 134, 11, 352, 341, 291, 349, 22, 120}, - {99, 139, 12, 453, 196, 277, 775, 40, 475, 33, 23, 401, 215, 51, 11, 14, 77, 111, 313, 130, 38, 211, 37, 266, 129, 15, 339, 153, 719, 3, 369, 515}, - {33, 77, 102, 4, 23, 128, 13, 141, 202, 64, 51, 0, 40, 59, 269, 115, 117, 137, 153, 1, 318, 11, 10, 177, 15, 134, 22, 90, 196, 2, 403, 32}, - {7, 2, 14, 58, 70, 112, 16, 5, 87, 38, 46, 52, 6, 128, 135, 1, 32, 21, 155, 29, 66, 64, 0, 97, 92, 186, 172, 294, 13, 23, 20, 37}, - {15, 13, 515, 1, 700, 2, 23, 0, 753, 5, 3, 4, 51, 10, 341, 115, 365, 180, 11, 33, 317, 77, 6, 7, 217, 12, 197, 165, 117, 9, 64, 102}, - {2, 1, 14, 29, 75, 69, 67, 6, 52, 46, 38, 24, 103, 220, 83, 25, 70, 87, 262, 74, 96, 267, 50, 366, 26, 16, 226, 394, 357, 66, 108, 19}, - {9, 105, 18, 39, 1, 0, 16, 557, 101, 272, 252, 890, 326, 49, 265, 21, 137, 100, 23, 938, 13, 310, 159, 5, 31, 24, 254, 51, 30, 128, 202, 132}, - {80, 209, 45, 61, 667, 17, 6, 106, 5, 2, 151, 29, 483, 255, 454, 833, 27, 311, 112, 19, 738, 378, 1, 58, 113, 26, 25, 469, 119, 887, 32, 64}, - {13, 23, 51, 15, 5, 1, 515, 0, 21, 2, 12, 141, 700, 165, 202, 115, 753, 32, 180, 4, 3, 197, 10, 120, 457, 9, 269, 128, 64, 341, 7, 33}, - {99, 12, 453, 277, 139, 157, 369, 474, 339, 51, 38, 23, 37, 196, 188, 401, 775, 111, 11, 313, 328, 475, 153, 266, 4, 471, 79, 40, 33, 629, 102, 14}, - {7, 92, 16, 232, 97, 140, 126, 14, 60, 107, 66, 35, 298, 387, 314, 104, 246, 462, 441, 150, 0, 38, 24, 2, 172, 357, 230, 330, 5, 633, 22, 289}, - {13, 77, 23, 202, 318, 141, 33, 4, 51, 269, 102, 177, 115, 403, 137, 2, 40, 494, 90, 11, 342, 128, 31, 117, 21, 32, 7, 12, 64, 134, 14, 10}, - {13, 2, 0, 23, 141, 1, 77, 3, 180, 33, 6, 64, 15, 10, 115, 51, 4, 5, 217, 197, 7, 165, 515, 102, 22, 11, 700, 269, 40, 352, 177, 14}, - {15, 515, 700, 753, 4, 11, 1, 93, 13, 5, 180, 110, 82, 21, 120, 23, 2, 33, 10, 141, 3, 165, 197, 102, 901, 0, 32, 341, 117, 40, 153, 12}, - {15, 515, 700, 753, 1, 13, 0, 2, 23, 4, 77, 51, 3, 5, 341, 291, 7, 33, 6, 115, 10, 9, 8, 217, 11, 177, 120, 180, 102, 165, 197, 365}, - {20, 43, 198, 325, 173, 904, 104, 234, 66, 147, 77, 319, 416, 422, 97, 426, 5, 0, 7, 450, 861, 202, 712, 725, 2, 32, 639, 376, 38, 324, 945, 315}, - {105, 0, 9, 28, 49, 301, 170, 1, 127, 159, 22, 16, 31, 98, 512, 623, 24, 109, 158, 395, 35, 68, 371, 65, 713, 55, 2, 242, 293, 21, 44, 18}, - {213, 88, 689, 466, 230, 30, 321, 435, 699, 352, 217, 201, 795, 831, 144, 854, 1, 443, 96, 539, 530, 840, 418, 251, 855, 190, 93, 100, 669, 31, 957, 662}, - {130, 453, 47, 196, 4, 57, 14, 59, 236, 711, 51, 153, 730, 77, 412, 381, 23, 202, 108, 128, 361, 13, 283, 117, 11, 719, 200, 46, 34, 78, 210, 2}, - {1, 2, 5, 14, 0, 50, 36, 22, 38, 46, 65, 67, 12, 86, 114, 28, 103, 29, 208, 7, 10, 128, 21, 83, 218, 23, 96, 54, 194, 6, 133, 51}, - {6, 26, 74, 19, 165, 453, 14, 730, 1, 125, 197, 50, 29, 51, 138, 357, 13, 2, 108, 391, 70, 719, 46, 457, 47, 500, 386, 262, 112, 23, 235, 52}, - {9, 10, 376, 20, 43, 0, 49, 18, 30, 120, 2, 33, 325, 104, 501, 470, 77, 788, 725, 102, 523, 39, 858, 5, 904, 414, 174, 55, 137, 37, 342, 13}, - {15, 515, 700, 753, 0, 1, 13, 23, 51, 77, 120, 202, 341, 82, 5, 4, 9, 260, 2, 137, 141, 128, 115, 351, 901, 8, 180, 10, 197, 21, 450, 33}, - {105, 131, 272, 578, 9, 49, 371, 219, 159, 616, 286, 320, 224, 187, 716, 98, 28, 22, 0, 623, 127, 258, 910, 737, 385, 31, 239, 347, 254, 109, 424, 95}, - {457, 51, 13, 23, 961, 12, 719, 99, 453, 15, 4, 515, 165, 401, 629, 3, 700, 11, 17, 14, 2, 37, 753, 41, 57, 569, 38, 45, 0, 33, 5, 32}, - {202, 120, 5, 33, 318, 77, 450, 102, 1, 260, 403, 128, 494, 21, 165, 13, 269, 12, 326, 23, 342, 523, 402, 2, 817, 64, 15, 141, 125, 82, 457, 475}, - {141, 269, 352, 217, 180, 64, 349, 137, 202, 160, 317, 15, 372, 515, 700, 752, 318, 753, 244, 13, 437, 291, 165, 864, 22, 237, 5, 82, 954, 21, 77, 418}, - {70, 29, 2, 145, 74, 112, 26, 6, 75, 52, 19, 66, 632, 1, 87, 220, 5, 135, 163, 287, 307, 25, 226, 7, 58, 396, 294, 278, 113, 409, 69, 151}, - {82, 351, 317, 15, 752, 180, 898, 352, 141, 901, 515, 341, 10, 700, 365, 1, 753, 498, 0, 217, 253, 115, 55, 854, 33, 5, 143, 32, 21, 160, 36, 197}, - {39, 9, 310, 254, 0, 30, 101, 49, 252, 272, 100, 265, 105, 455, 159, 557, 190, 333, 286, 688, 18, 166, 1, 158, 709, 16, 625, 627, 31, 131, 327, 329}, - {2, 58, 29, 5, 1, 151, 186, 52, 70, 45, 7, 549, 14, 75, 112, 400, 113, 155, 61, 46, 227, 163, 311, 315, 66, 6, 307, 27, 17, 220, 287, 74}, - {141, 217, 13, 21, 352, 23, 269, 77, 180, 115, 317, 64, 202, 15, 349, 137, 5, 51, 165, 291, 318, 752, 372, 4, 0, 102, 33, 365, 197, 32, 341, 125}, - {68, 35, 0, 9, 65, 101, 149, 124, 24, 154, 175, 16, 28, 7, 67, 1, 18, 189, 114, 398, 55, 14, 345, 39, 118, 133, 69, 2, 230, 429, 71, 283}, - {66, 7, 29, 2, 112, 52, 20, 43, 97, 151, 74, 192, 135, 5, 173, 525, 337, 45, 145, 58, 415, 25, 14, 32, 644, 70, 544, 226, 222, 21, 6, 580}, - {31, 125, 44, 22, 116, 299, 242, 55, 1, 170, 64, 36, 479, 870, 456, 685, 10, 599, 558, 0, 268, 506, 28, 740, 23, 903, 492, 164, 393, 206, 2, 86}, - {188, 11, 79, 12, 99, 377, 94, 33, 542, 339, 40, 474, 111, 37, 4, 51, 102, 453, 139, 775, 13, 475, 23, 961, 277, 471, 134, 57, 431, 266, 115, 117}, - {658, 698, 340, 98, 296, 303, 1, 31, 850, 363, 156, 919, 44, 774, 586, 385, 120, 77, 82, 10, 223, 30, 354, 291, 23, 914, 478, 87, 260, 163, 48, 13}, - {15, 515, 700, 753, 82, 4, 1, 13, 901, 33, 197, 11, 5, 10, 23, 165, 2, 0, 180, 3, 21, 77, 51, 120, 365, 115, 217, 40, 117, 102, 32, 401}, - {15, 515, 700, 753, 4, 11, 5, 13, 1, 141, 3, 180, 23, 202, 21, 2, 269, 64, 165, 33, 40, 32, 0, 318, 120, 128, 12, 197, 117, 352, 51, 17}, - {91, 6, 233, 85, 370, 718, 81, 65, 25, 256, 63, 343, 42, 74, 235, 123, 138, 511, 397, 249, 26, 194, 650, 355, 64, 87, 544, 18, 90, 643, 66, 214}, - {23, 13, 202, 51, 21, 120, 1, 5, 141, 128, 450, 64, 318, 403, 15, 137, 260, 33, 12, 48, 32, 31, 125, 494, 269, 102, 165, 515, 77, 2, 197, 14}, - {180, 317, 365, 341, 752, 217, 115, 352, 901, 482, 372, 498, 1, 141, 15, 253, 515, 244, 2, 700, 0, 21, 13, 82, 23, 4, 579, 351, 753, 291, 269, 77}, - {13, 115, 197, 341, 9, 352, 468, 237, 64, 498, 23, 165, 22, 509, 901, 546, 482, 180, 28, 569, 317, 51, 365, 873, 391, 95, 86, 217, 49, 837, 752, 706}, - {13, 23, 51, 1, 141, 5, 165, 202, 21, 120, 64, 125, 180, 15, 2, 33, 197, 115, 128, 32, 260, 269, 12, 82, 4, 515, 137, 7, 318, 93, 0, 700}, - {214, 289, 90, 174, 874, 6, 138, 280, 65, 81, 64, 85, 355, 751, 194, 233, 312, 348, 835, 91, 0, 32, 343, 636, 249, 29, 875, 288, 519, 104, 247, 74}, - {15, 515, 700, 753, 4, 5, 11, 13, 1, 33, 23, 21, 2, 3, 102, 32, 141, 77, 180, 117, 31, 64, 0, 40, 134, 196, 120, 352, 12, 44, 197, 6}, - {33, 15, 13, 515, 117, 23, 700, 217, 134, 753, 0, 51, 153, 77, 141, 2, 4, 64, 196, 1, 3, 180, 10, 115, 5, 102, 6, 11, 22, 202, 165, 7}, - {15, 515, 700, 753, 33, 4, 77, 102, 1, 40, 13, 117, 11, 115, 134, 5, 21, 153, 23, 217, 3, 32, 2, 317, 120, 196, 180, 141, 51, 12, 59, 260}, - {15, 515, 700, 753, 13, 0, 1, 23, 2, 217, 51, 3, 4, 5, 8, 317, 115, 9, 341, 10, 202, 180, 6, 365, 7, 82, 457, 22, 120, 901, 33, 291}, - {7, 2, 135, 20, 97, 14, 66, 52, 337, 673, 192, 29, 43, 355, 353, 5, 16, 294, 107, 376, 147, 226, 331, 560, 64, 470, 222, 104, 415, 32, 4, 324}, - {195, 132, 142, 167, 146, 77, 363, 271, 121, 354, 202, 120, 647, 178, 786, 212, 687, 0, 101, 878, 16, 522, 60, 5, 450, 411, 35, 55, 98, 639, 259, 318}, - {202, 77, 20, 0, 318, 66, 104, 128, 102, 269, 177, 43, 33, 7, 216, 291, 494, 5, 2, 342, 74, 173, 97, 112, 450, 22, 337, 10, 234, 52, 64, 678}, - {107, 362, 612, 356, 359, 97, 414, 43, 259, 20, 392, 7, 298, 147, 819, 683, 465, 173, 729, 660, 319, 14, 5, 779, 581, 595, 246, 35, 501, 92, 0, 230}, - {6, 165, 14, 453, 13, 51, 19, 23, 386, 457, 74, 391, 308, 2, 26, 401, 47, 758, 603, 108, 719, 366, 1, 29, 309, 730, 324, 197, 133, 70, 115, 867}, - {179, 72, 205, 180, 247, 245, 4, 490, 352, 59, 317, 152, 79, 498, 94, 217, 148, 76, 752, 864, 11, 216, 141, 405, 89, 452, 197, 111, 497, 188, 37, 21}, - {107, 7, 298, 314, 14, 359, 32, 392, 232, 279, 172, 97, 60, 581, 387, 126, 121, 0, 534, 493, 356, 92, 441, 95, 13, 21, 35, 147, 22, 5, 16, 362}, - {156, 271, 354, 586, 360, 132, 591, 195, 121, 18, 340, 1, 5, 13, 21, 48, 668, 446, 23, 463, 296, 658, 60, 55, 407, 698, 146, 70, 626, 51, 163, 24}, - {13, 23, 51, 4, 0, 12, 457, 15, 11, 453, 2, 515, 5, 1, 99, 10, 115, 165, 700, 475, 401, 403, 3, 961, 40, 14, 37, 753, 719, 32, 64, 569}, - {48, 125, 21, 165, 13, 221, 23, 763, 423, 508, 197, 5, 98, 92, 193, 16, 441, 386, 64, 314, 293, 457, 391, 140, 49, 60, 102, 693, 683, 51, 35, 867}, - {202, 77, 120, 450, 5, 318, 1, 494, 0, 195, 18, 132, 523, 403, 326, 604, 354, 260, 121, 576, 203, 167, 234, 817, 682, 49, 35, 615, 21, 20, 13, 102}, - {39, 9, 166, 30, 0, 101, 158, 68, 404, 190, 333, 274, 252, 310, 88, 100, 49, 28, 344, 35, 21, 22, 419, 131, 438, 1, 16, 65, 530, 694, 124, 10}, - {15, 515, 700, 753, 110, 4, 1, 11, 165, 180, 93, 13, 82, 5, 2, 197, 33, 120, 0, 3, 10, 23, 21, 115, 901, 217, 341, 77, 317, 51, 32, 117}, - {2, 29, 1, 14, 6, 52, 5, 46, 50, 26, 70, 19, 103, 58, 38, 67, 96, 262, 516, 309, 218, 133, 108, 27, 75, 17, 112, 114, 24, 487, 331, 83}, - {120, 77, 15, 13, 1, 141, 260, 23, 515, 217, 110, 51, 137, 700, 317, 202, 165, 291, 180, 21, 753, 128, 0, 177, 326, 93, 450, 82, 64, 269, 197, 5}, - {255, 59, 554, 297, 183, 56, 33, 444, 108, 358, 123, 196, 269, 122, 77, 153, 57, 177, 117, 730, 19, 467, 605, 130, 128, 50, 275, 4, 291, 475, 134, 133}, - {13, 23, 51, 12, 153, 14, 117, 120, 165, 134, 99, 401, 38, 453, 15, 128, 197, 719, 64, 515, 475, 403, 37, 33, 196, 700, 40, 125, 5, 0, 54, 2}, - {64, 33, 174, 348, 95, 108, 467, 554, 56, 0, 25, 306, 233, 6, 63, 511, 343, 120, 13, 85, 29, 561, 543, 707, 319, 180, 899, 355, 77, 49, 256, 18}, - {120, 260, 51, 23, 77, 15, 202, 1, 93, 82, 141, 450, 13, 326, 515, 137, 21, 5, 64, 33, 110, 700, 128, 165, 318, 203, 269, 102, 351, 753, 197, 125}, - {15, 515, 700, 753, 4, 13, 11, 1, 5, 21, 23, 2, 33, 64, 3, 180, 32, 141, 22, 102, 77, 0, 10, 93, 82, 352, 117, 40, 341, 31, 165, 6}, - {15, 515, 700, 753, 341, 13, 23, 141, 33, 1, 0, 217, 4, 77, 180, 10, 82, 351, 51, 137, 5, 64, 9, 317, 21, 11, 102, 40, 260, 202, 854, 115}, - {105, 272, 131, 22, 327, 286, 28, 239, 320, 9, 109, 578, 219, 49, 98, 224, 95, 159, 538, 371, 616, 127, 187, 64, 713, 55, 0, 170, 168, 258, 716, 623}, - {16, 18, 68, 35, 24, 60, 71, 118, 92, 126, 0, 9, 101, 191, 7, 55, 154, 175, 212, 14, 167, 150, 302, 28, 375, 1, 107, 124, 346, 273, 21, 108}, - {20, 147, 43, 470, 376, 142, 904, 178, 427, 798, 0, 595, 198, 325, 858, 319, 61, 202, 173, 97, 5, 422, 14, 22, 107, 259, 32, 49, 887, 77, 414, 392}, - {13, 23, 51, 12, 33, 15, 99, 64, 128, 515, 453, 202, 117, 153, 37, 102, 700, 40, 134, 196, 120, 0, 2, 753, 141, 14, 38, 3, 82, 403, 77, 21}, - {383, 17, 62, 136, 84, 119, 56, 440, 3, 504, 240, 80, 378, 129, 123, 548, 106, 128, 4, 11, 14, 555, 162, 32, 184, 361, 59, 64, 205, 5, 469, 57}, - {70, 1, 48, 652, 5, 638, 846, 888, 21, 349, 269, 260, 340, 562, 767, 761, 163, 883, 774, 141, 125, 518, 591, 0, 23, 9, 87, 13, 371, 303, 622, 31}, - {66, 135, 6, 97, 74, 278, 69, 7, 14, 324, 267, 172, 2, 140, 462, 1, 357, 38, 808, 550, 92, 841, 189, 29, 16, 25, 298, 87, 75, 204, 24, 335}, - {51, 23, 33, 13, 102, 40, 12, 128, 64, 77, 10, 202, 0, 196, 117, 4, 14, 99, 134, 453, 65, 153, 11, 475, 139, 403, 22, 141, 86, 2, 21, 15}, - {88, 100, 264, 166, 274, 435, 772, 1, 382, 921, 96, 478, 30, 438, 639, 909, 897, 521, 190, 466, 960, 410, 9, 144, 530, 418, 31, 329, 265, 691, 778, 93}, - {62, 440, 136, 56, 84, 3, 504, 548, 555, 383, 4, 17, 129, 128, 507, 361, 123, 59, 119, 162, 14, 57, 152, 328, 161, 11, 202, 495, 184, 27, 80, 215}, - {911, 617, 332, 959, 206, 141, 253, 244, 282, 384, 110, 120, 10, 260, 352, 143, - 951, 811, 269, 373, 160, 417, 93, 531, 728, 203, 434, 940, 137, 55, 36, 717}, - {120, 15, 260, 141, 77, 1, 515, 82, 700, 351, 33, 23, 450, 13, 110, 326, 64, 217, 269, 753, 203, 137, 102, 5, 165, 21, 51, 291, 93, 177, 373, 128}, - {15, 515, 700, 753, 0, 1, 2, 23, 13, 51, 5, 9, 82, 901, 180, 8, 3, 4, 120, 6, 7, 141, 93, 12, 197, 341, 10, 33, 115, 730, 64, 125}, - {7, 104, 97, 107, 356, 232, 66, 560, 298, 289, 14, 707, 38, 568, 359, 64, 20, 0, 65, 324, 22, 214, 92, 32, 192, 5, 387, 43, 712, 90, 172, 95}, - {6, 1, 2, 66, 67, 14, 74, 24, 108, 29, 69, 83, 458, 7, 25, 38, 135, 103, 36, 150, 451, 114, 52, 594, 75, 65, 380, 18, 267, 602, 19, 278}, - {13, 23, 51, 12, 115, 21, 202, 5, 457, 15, 4, 1, 64, 719, 0, 403, 2, 3, 453, 165, 99, 141, 401, 128, 32, 515, 10, 37, 523, 197, 120, 700}, - {57, 59, 4, 11, 412, 381, 77, 53, 421, 291, 250, 368, 99, 14, 27, 369, 803, 283, 23, 108, 403, 19, 339, 210, 0, 401, 12, 444, 236, 40, 361, 736}, - {15, 515, 700, 1, 0, 753, 2, 13, 23, 5, 51, 180, 3, 115, 6, 7, 457, 4, 9, 8, 12, 82, 197, 165, 141, 901, 120, 719, 33, 64, 21, 22}, - {64, 95, 180, 247, 929, 146, 90, 126, 197, 32, 237, 60, 288, 165, 316, 92, 5, 13, 77, 7, 217, 955, 522, 22, 16, 314, 132, 4, 317, 10, 312, 86}, - {15, 1, 120, 13, 23, 515, 0, 51, 700, 180, 141, 2, 5, 202, 21, 260, 753, 165, 137, 33, 77, 110, 197, 128, 326, 7, 450, 4, 102, 9, 269, 12}, - {14, 2, 16, 46, 1, 7, 24, 69, 75, 35, 38, 50, 29, 220, 52, 140, 267, 67, 18, 54, 70, 309, 5, 60, 92, 189, 171, 87, 71, 163, 58, 0}, - {31, 98, 127, 44, 9, 299, 0, 276, 293, 284, 116, 49, 935, 599, 105, 22, 456, 201, 28, 1, 39, 125, 242, 137, 371, 144, 131, 492, 159, 272, 51, 395}, - {6, 27, 151, 53, 573, 445, 297, 113, 26, 73, 436, 19, 491, 250, 396, 315, 45, 112, 145, 58, 614, 881, 25, 34, 611, 200, 17, 80, 70, 5, 138, 631}, - {32, 693, 81, 788, 90, 804, 403, 56, 494, 21, 84, 397, 202, 65, 18, 77, 64, 681, 214, 725, 523, 784, 526, 33, 102, 825, 240, 0, 115, 241, 817, 91}, - {24, 7, 14, 2, 18, 16, 65, 0, 108, 149, 28, 69, 1, 71, 154, 36, 124, 35, 67, 140, 189, 429, 92, 68, 66, 22, 55, 118, 302, 150, 9, 6}, - {0, 68, 9, 35, 65, 101, 189, 212, 114, 67, 124, 69, 1, 154, 149, 39, 230, 64, 252, 16, 88, 702, 103, 100, 18, 336, 28, 329, 520, 83, 30, 755}, - {5, 2, 186, 29, 61, 45, 17, 1, 52, 48, 58, 171, 155, 227, 80, 209, 311, 21, 14, 46, 50, 106, 243, 513, 334, 502, 496, 38, 3, 6, 32, 592}, - {15, 515, 700, 753, 13, 1, 2, 0, 3, 4, 5, 23, 341, 11, 10, 33, 6, 51, 165, 117, 153, 7, 180, 12, 365, 901, 77, 569, 197, 115, 64, 9}, - {13, 15, 23, 515, 0, 51, 1, 700, 4, 2, 753, 10, 3, 5, 12, 77, 33, 961, 165, 457, 197, 11, 115, 9, 22, 102, 40, 403, 202, 21, 14, 59}, - {15, 515, 700, 753, 13, 0, 1, 23, 2, 33, 102, 5, 4, 10, 9, 3, 51, 115, 77, 7, 6, 341, 12, 11, 217, 40, 457, 196, 180, 165, 8, 523}, - {166, 39, 30, 274, 190, 100, 333, 438, 530, 310, 88, 252, 0, 9, 539, 265, 1, 656, 404, 101, 625, 131, 778, 254, 31, 455, 676, 329, 724, 158, 21, 23}, - {734, 148, 94, 308, 431, 115, 37, 89, 111, 413, 79, 468, 197, 629, 341, 474, 569, 12, 13, 873, 179, 401, 11, 4, 180, 23, 205, 72, 59, 365, 134, 51}, - {539, 228, 224, 219, 816, 190, 30, 258, 871, 840, 669, 93, 406, 530, 957, 187, 160, 531, 748, 137, 131, 88, 863, 36, 728, 839, 44, 213, 352, 116, 202, 466}, - {393, 791, 125, 801, 730, 551, 386, 23, 31, 175, 93, 98, 51, 13, 144, 788, 126, 203, 21, 345, 116, 22, 949, 110, 575, 165, 326, 44, 0, 4, 60, 221}, - {13, 23, 77, 141, 0, 4, 51, 2, 33, 115, 64, 1, 10, 3, 6, 15, 11, 102, 7, 217, 180, 40, 515, 22, 128, 177, 202, 9, 700, 269, 165, 5}, - {2, 29, 7, 70, 52, 14, 1, 58, 112, 46, 75, 5, 171, 163, 87, 220, 307, 151, 186, 334, 38, 66, 155, 16, 69, 135, 278, 45, 262, 97, 6, 21}, - {88, 321, 213, 100, 230, 435, 689, 466, 1, 382, 30, 352, 217, 699, 410, 96, 795, 36, 921, 752, 190, 141, 144, 180, 44, 831, 317, 83, 443, 31, 840, 251}, - {363, 411, 101, 520, 354, 9, 195, 668, 132, 156, 447, 1, 905, 364, 18, 23, 765, 664, 146, 5, 360, 13, 121, 96, 98, 31, 252, 39, 100, 759, 264, 551}, - {13, 23, 51, 730, 12, 719, 453, 457, 401, 475, 5, 21, 403, 2, 0, 1, 15, 4, 3, 899, 99, 32, 165, 11, 515, 308, 197, 115, 6, 961, 700, 523}, - {72, 76, 89, 12, 37, 4, 308, 179, 38, 528, 90, 431, 54, 205, 148, 184, 401, 57, 152, 474, 23, 59, 51, 245, 428, 11, 32, 99, 405, 316, 257, 21}, - {376, 20, 43, 147, 470, 173, 97, 595, 107, 319, 414, 142, 819, 5, 729, 178, 858, 7, 427, 32, 426, 104, 14, 0, 392, 362, 259, 61, 230, 77, 560, 246}, - {202, 141, 269, 494, 318, 137, 51, 128, 403, 4, 217, 96, 77, 5, 64, 177, 291, 180, 15, 352, 102, 10, 33, 349, 2, 317, 0, 341, 120, 515, 21, 453}, - {77, 202, 33, 128, 102, 318, 494, 269, 13, 0, 117, 23, 342, 291, 403, 15, 134, 51, 153, 141, 177, 515, 82, 137, 196, 700, 203, 64, 22, 351, 753, 4}, - {253, 110, 951, 352, 499, 811, 10, 854, 180, 638, 244, 559, 642, 752, 564, 8, 141, 143, 417, 341, 901, 260, 206, 197, 922, 661, 93, 15, 498, 373, 165, 911}, - {141, 13, 23, 180, 4, 217, 5, 1, 269, 317, 21, 0, 2, 202, 115, 51, 352, 77, 3, 197, 64, 341, 318, 15, 291, 9, 137, 93, 32, 165, 515, 33}, - {9, 0, 18, 252, 16, 101, 68, 39, 24, 118, 35, 109, 158, 329, 28, 167, 60, 364, 333, 265, 49, 100, 22, 419, 553, 55, 1, 677, 71, 7, 212, 159}, - {28, 109, 9, 39, 0, 158, 49, 22, 168, 35, 55, 175, 1, 65, 67, 185, 194, 159, 289, 95, 272, 114, 30, 105, 86, 584, 36, 169, 254, 2, 83, 24}, - {15, 515, 13, 700, 1, 753, 2, 23, 0, 3, 4, 5, 33, 341, 11, 51, 6, 10, 197, 115, 901, 180, 77, 40, 102, 12, 365, 165, 141, 217, 7, 317}, - {173, 693, 104, 422, 5, 18, 61, 32, 102, 0, 20, 13, 784, 560, 33, 66, 397, 526, 49, 207, 29, 25, 510, 707, 65, 6, 11, 344, 21, 263, 81, 77}, - {23, 13, 386, 51, 308, 801, 719, 221, 401, 949, 21, 730, 165, 421, 102, 115, 125, 33, 341, 670, 468, 117, 770, 1, 120, 6, 197, 14, 403, 97, 67, 958}, - {0, 49, 105, 16, 28, 24, 159, 9, 158, 320, 1, 68, 35, 239, 170, 18, 109, 7, 55, 65, 2, 95, 301, 124, 347, 14, 21, 154, 22, 127, 286, 31}, - {2, 5, 1, 207, 45, 29, 32, 58, 76, 61, 6, 263, 292, 655, 72, 14, 17, 476, 7, 119, 52, 306, 70, 64, 21, 90, 186, 214, 106, 38, 3, 790}, - {21, 6, 125, 49, 13, 64, 715, 66, 115, 95, 197, 33, 22, 32, 204, 165, 56, 278, 0, 408, 241, 120, 4, 808, 681, 350, 263, 85, 81, 571, 135, 509}, - {612, 427, 325, 107, 202, 5, 376, 49, 64, 392, 403, 470, 21, 147, 31, 788, 494, 14, 362, 465, 858, 98, 20, 804, 518, 43, 845, 318, 125, 97, 725, 534}, - {32, 21, 76, 72, 2, 1, 14, 5, 241, 449, 89, 38, 350, 221, 155, 48, 50, 292, 37, 46, 45, 90, 270, 54, 17, 179, 214, 12, 148, 430, 476, 413}, - {24, 0, 28, 16, 7, 124, 35, 154, 14, 149, 65, 18, 9, 68, 55, 108, 175, 71, 2, 1, 22, 109, 92, 67, 484, 336, 118, 69, 302, 398, 570, 420}, - {1, 5, 14, 2, 48, 50, 38, 67, 46, 21, 0, 54, 45, 270, 281, 12, 24, 32, 155, 96, 513, 103, 290, 83, 61, 58, 36, 17, 37, 72, 69, 181}, - {13, 961, 569, 197, 37, 15, 23, 474, 515, 94, 148, 111, 12, 165, 629, 341, 700, 79, 901, 401, 51, 405, 753, 10, 134, 4, 115, 734, 873, 11, 89, 117}, - {33, 23, 102, 51, 13, 40, 77, 128, 64, 202, 141, 15, 4, 12, 0, 1, 2, 117, 22, 11, 10, 403, 153, 515, 99, 318, 137, 269, 139, 196, 700, 134}, - {0, 1, 24, 67, 9, 16, 18, 35, 28, 69, 103, 50, 5, 2, 65, 12, 83, 68, 7, 96, 14, 22, 21, 149, 75, 114, 13, 133, 23, 71, 218, 54}, - {384, 617, 940, 332, 855, 911, 206, 959, 434, 282, 141, 10, 93, 253, 244, 110, 144, 268, 120, 36, 352, 137, 417, 203, 116, 31, 44, 269, 160, 201, 143, 951}, - {30, 93, 473, 137, 31, 704, 450, 652, 190, 203, 800, 254, 166, 274, 326, 144, 269, 160, 127, 303, 120, 625, 88, 848, 110, 435, 77, 521, 349, 131, 340, 744}, - {53, 27, 73, 26, 19, 250, 297, 200, 25, 630, 17, 6, 611, 122, 34, 42, 714, 235, 472, 65, 436, 14, 80, 684, 690, 106, 45, 113, 680, 108, 64, 4}, - {15, 515, 1, 2, 700, 0, 753, 3, 5, 141, 180, 4, 13, 77, 33, 10, 217, 6, 7, 134, 11, 352, 197, 64, 165, 341, 317, 23, 12, 115, 102, 40}, - {254, 530, 39, 613, 688, 221, 30, 31, 438, 190, 228, 960, 1, 44, 141, 21, 180, 406, 23, 166, 9, 202, 13, 96, 137, 48, 131, 829, 317, 269, 393, 51}, - {9, 39, 28, 35, 30, 166, 158, 36, 0, 175, 101, 346, 364, 67, 49, 68, 168, 420, 88, 1, 194, 131, 100, 352, 55, 83, 190, 64, 137, 570, 86, 65}, - {62, 56, 3, 548, 555, 507, 440, 161, 34, 4, 215, 136, 162, 514, 361, 527, 17, 14, 211, 130, 328, 11, 383, 123, 84, 183, 38, 57, 184, 152, 205, 494}, - {92, 126, 107, 7, 356, 493, 97, 279, 359, 298, 16, 246, 35, 60, 14, 441, 362, 121, 43, 423, 5, 132, 392, 20, 508, 230, 199, 146, 232, 173, 150, 414}, - {15, 82, 141, 515, 291, 922, 349, 700, 217, 260, 372, 120, 351, 93, 77, 753, 318, 352, 373, 854, 1, 326, 269, 21, 13, 102, 144, 202, 64, 23, 203, 137}, - {141, 217, 352, 115, 180, 13, 269, 317, 752, 77, 23, 21, 341, 197, 5, 372, 244, 291, 9, 64, 51, 102, 4, 1, 365, 2, 165, 33, 3, 48, 237, 351}, - {78, 47, 390, 19, 130, 453, 108, 27, 711, 813, 730, 444, 412, 283, 196, 690, 123, 14, 128, 26, 250, 389, 650, 236, 200, 65, 51, 4, 34, 183, 297, 73}, - {34, 250, 297, 80, 472, 64, 495, 17, 311, 3, 148, 45, 667, 61, 176, 53, 243, 27, 90, 161, 469, 141, 483, 151, 62, 128, 29, 4, 58, 56, 5, 231}, - {51, 23, 33, 13, 551, 77, 102, 326, 421, 21, 523, 120, 5, 899, 453, 692, 202, 153, 308, 615, 115, 958, 450, 401, 791, 68, 221, 93, 475, 18, 403, 4}, - {98, 223, 393, 363, 411, 1, 478, 834, 664, 156, 284, 691, 447, 791, 914, 293, 354, 724, 697, 9, 807, 541, 759, 51, 18, 421, 48, 264, 948, 586, 195, 848}, - {7, 14, 107, 232, 16, 92, 2, 60, 46, 5, 359, 121, 24, 526, 220, 620, 135, 1, 172, 21, 126, 314, 132, 77, 18, 75, 32, 278, 12, 23, 52, 38}, - {32, 76, 2, 1, 21, 72, 241, 14, 5, 48, 292, 89, 476, 45, 720, 270, 179, 90, 17, 214, 148, 38, 50, 29, 129, 155, 350, 46, 290, 227, 123, 464}, - {15, 515, 700, 753, 13, 23, 33, 77, 51, 4, 102, 0, 32, 202, 1, 11, 128, 82, 117, 141, 40, 5, 110, 8, 3, 90, 137, 21, 10, 318, 403, 165}, - {66, 6, 69, 2, 1, 74, 14, 135, 278, 267, 380, 24, 29, 97, 67, 38, 103, 75, 7, 388, 324, 25, 52, 150, 87, 83, 189, 357, 335, 108, 204, 172}, - {152, 4, 339, 59, 79, 471, 188, 11, 77, 94, 128, 33, 529, 377, 12, 111, 102, 202, 452, 402, 216, 99, 13, 542, 51, 40, 474, 37, 64, 291, 23, 961}, - {15, 515, 700, 753, 1, 0, 196, 13, 33, 2, 77, 5, 23, 102, 3, 10, 9, 7, 217, 4, 6, 153, 117, 177, 14, 457, 115, 12, 40, 730, 11, 134}, - {17, 209, 45, 106, 207, 5, 255, 119, 62, 2, 61, 3, 263, 742, 306, 655, 425, 378, 32, 56, 29, 136, 84, 80, 311, 58, 186, 240, 243, 383, 14, 21}, - {120, 260, 450, 15, 1, 23, 817, 13, 515, 523, 326, 5, 700, 51, 82, 31, 202, 64, 21, 753, 318, 93, 32, 269, 98, 33, 351, 77, 102, 125, 457, 165}, - {116, 492, 268, 93, 23, 206, 203, 0, 551, 918, 13, 51, 8, 22, 417, 940, 120, 10, 499, 31, 949, 791, 125, 523, 165, 473, 341, 730, 421, 959, 401, 391}, - {15, 515, 700, 753, 165, 13, 0, 1, 197, 23, 4, 82, 120, 2, 180, 12, 260, 719, 8, 3, 386, 117, 5, 523, 901, 11, 341, 51, 10, 9, 141, 351}, - {14, 24, 69, 7, 2, 66, 108, 1, 67, 6, 36, 398, 18, 267, 150, 97, 29, 38, 83, 149, 65, 74, 28, 0, 189, 71, 388, 16, 273, 124, 46, 22}, - {330, 96, 523, 335, 367, 662, 141, 839, 1, 922, 372, 615, 244, 717, 269, 443, 418, 352, 403, 692, 217, 854, 752, 180, 36, 64, 498, 576, 349, 201, 98, 284}, - {184, 90, 257, 205, 245, 229, 57, 152, 769, 17, 524, 5, 32, 497, 45, 432, 619, 2, 452, 266, 4, 106, 1, 21, 179, 59, 76, 3, 460, 292, 381, 128}, - {7, 14, 16, 2, 46, 5, 70, 107, 87, 13, 58, 307, 92, 32, 38, 23, 202, 0, 172, 24, 18, 21, 60, 128, 77, 35, 20, 10, 9, 4, 171, 112}, - {7, 66, 140, 16, 14, 92, 97, 69, 267, 172, 189, 24, 380, 2, 35, 60, 298, 451, 230, 135, 314, 74, 150, 71, 38, 357, 6, 330, 67, 423, 21, 443}, - {121, 167, 354, 132, 18, 446, 147, 101, 212, 146, 407, 16, 55, 35, 647, 191, 20, 271, 199, 68, 60, 259, 463, 107, 9, 126, 363, 7, 195, 43, 14, 411}, - {76, 90, 179, 32, 205, 21, 184, 460, 257, 288, 45, 245, 316, 5, 57, 152, 241, 2, 358, 1, 229, 72, 524, 148, 48, 769, 17, 4, 12, 38, 14, 720}, - {147, 259, 178, 878, 427, 465, 581, 198, 786, 798, 142, 534, 325, 929, 20, 362, 35, 132, 107, 376, 43, 5, 279, 77, 49, 146, 70, 202, 590, 771, 33, 14}, - {473, 93, 450, 778, 141, 30, 855, 466, 144, 203, 330, 530, 88, 523, 459, 372, 201, 617, 839, 704, 254, 321, 934, 326, 39, 36, 82, 717, 332, 213, 559, 403}, - {523, 475, 51, 899, 730, 453, 23, 719, 403, 33, 457, 13, 421, 386, 4, 120, 117, 196, 102, 153, 15, 801, 450, 817, 515, 260, 202, 11, 700, 99, 165, 125}, - {15, 1, 13, 515, 0, 2, 700, 5, 23, 753, 4, 3, 341, 317, 10, 115, 180, 11, 33, 64, 217, 77, 117, 165, 197, 7, 6, 365, 9, 141, 102, 134}, - {19, 4, 119, 40, 33, 202, 27, 84, 102, 56, 77, 73, 504, 485, 26, 494, 757, 63, 862, 59, 23, 300, 25, 12, 128, 11, 5, 13, 342, 880, 469, 6}, - {32, 20, 2, 13, 5, 21, 23, 6, 12, 38, 43, 29, 64, 7, 95, 51, 61, 207, 48, 147, 90, 178, 17, 182, 49, 0, 115, 202, 52, 362, 37, 22}, - {339, 188, 11, 79, 4, 94, 377, 12, 99, 111, 542, 102, 37, 33, 474, 51, 471, 40, 453, 152, 77, 13, 59, 403, 342, 23, 117, 57, 475, 134, 128, 38}, - {34, 128, 283, 176, 495, 231, 318, 432, 503, 275, 529, 527, 161, 53, 3, 202, 56, 291, 585, 469, 73, 17, 14, 412, 57, 27, 80, 245, 250, 381, 402, 51}, - {15, 515, 13, 700, 1, 217, 141, 120, 23, 180, 753, 115, 365, 51, 317, 341, 77, 260, 0, 291, 110, 137, 202, 5, 21, 269, 64, 36, 349, 2, 4, 10}, - {13, 15, 961, 515, 700, 753, 4, 12, 2, 457, 3, 11, 197, 51, 37, 569, 115, 23, 5, 0, 99, 10, 1, 134, 6, 111, 165, 33, 72, 40, 38, 79}, - {15, 515, 700, 753, 13, 1, 0, 2, 23, 33, 5, 3, 10, 4, 9, 115, 7, 102, 6, 51, 12, 217, 77, 11, 40, 457, 569, 341, 117, 317, 14, 719}, - {5, 76, 2, 32, 292, 214, 45, 1, 129, 519, 123, 179, 90, 710, 17, 29, 460, 72, 14, 207, 21, 249, 58, 205, 464, 263, 618, 48, 6, 245, 3, 257}, - {72, 76, 32, 4, 21, 12, 38, 23, 99, 54, 89, 3, 14, 17, 51, 57, 11, 90, 13, 488, 179, 2, 59, 148, 45, 37, 5, 115, 401, 1, 10, 421}, - {98, 223, 393, 1, 834, 264, 284, 791, 724, 293, 478, 772, 697, 909, 363, 682, 905, 447, 541, 821, 411, 51, 421, 9, 807, 48, 765, 31, 730, 96, 386, 410}, - {341, 13, 509, 8, 23, 638, 165, 901, 762, 10, 569, 242, 391, 197, 873, 642, 506, 499, 629, 961, 15, 180, 116, 456, 206, 546, 417, 1, 338, 457, 515, 867}, - {1, 2, 5, 50, 14, 38, 46, 114, 0, 36, 29, 22, 218, 65, 86, 96, 137, 21, 133, 285, 12, 10, 323, 181, 17, 58, 51, 23, 67, 7, 28, 6}, - {481, 878, 202, 13, 5, 23, 182, 32, 269, 21, 1, 318, 77, 142, 557, 494, 141, 33, 640, 137, 70, 291, 2, 51, 260, 415, 929, 403, 120, 58, 4, 259}, - {15, 515, 700, 753, 1, 4, 13, 0, 2, 5, 341, 3, 11, 180, 134, 12, 10, 317, 197, 365, 33, 21, 23, 165, 117, 6, 77, 7, 217, 37, 32, 498}, - {25, 119, 19, 6, 26, 42, 27, 17, 4, 790, 45, 814, 2, 469, 483, 84, 122, 1, 0, 33, 32, 128, 76, 80, 611, 113, 73, 56, 5, 240, 202, 77}, - {14, 2, 7, 1, 24, 0, 65, 6, 16, 69, 67, 22, 124, 28, 108, 5, 18, 36, 86, 10, 38, 46, 66, 398, 289, 168, 12, 83, 21, 23, 610, 13}, - {51, 23, 128, 13, 15, 202, 12, 120, 33, 64, 141, 82, 10, 515, 0, 403, 700, 3, 1, 99, 117, 269, 153, 165, 753, 5, 318, 197, 102, 260, 2, 137}, - {16, 35, 24, 0, 9, 18, 7, 1, 68, 69, 50, 71, 103, 65, 67, 189, 133, 23, 28, 13, 60, 537, 149, 335, 75, 21, 64, 5, 114, 2, 12, 14}, - {754, 803, 133, 576, 880, 543, 2, 1, 657, 50, 14, 38, 46, 5, 29, 67, 218, 36, 58, 171, 52, 96, 24, 103, 775, 0, 114, 83, 181, 54, 65, 45}, - {21, 32, 5, 3, 2, 17, 14, 72, 76, 1, 12, 23, 38, 51, 4, 54, 10, 0, 89, 13, 99, 137, 45, 36, 421, 115, 543, 11, 22, 128, 221, 48}, - {434, 384, 268, 144, 855, 940, 617, 206, 332, 116, 93, 911, 959, 282, 203, 137, 141, 489, 44, 120, 10, 110, 244, 36, 98, 31, 269, 253, 367, 417, 160, 9}, - {15, 2, 1, 0, 13, 515, 5, 700, 3, 23, 180, 217, 141, 10, 753, 4, 117, 6, 77, 33, 64, 7, 11, 197, 352, 317, 341, 134, 165, 115, 12, 9}, - {2, 113, 6, 25, 1, 0, 29, 4, 7, 833, 5, 45, 32, 61, 128, 19, 77, 151, 74, 145, 64, 42, 14, 210, 655, 106, 59, 177, 27, 17, 21, 738}, - {116, 268, 918, 203, 551, 31, 8, 692, 206, 791, 403, 499, 417, 93, 940, 421, 0, 23, 22, 120, 13, 523, 44, 51, 299, 473, 959, 1, 10, 475, 202, 125}, - {107, 126, 132, 612, 362, 279, 20, 146, 259, 493, 199, 121, 590, 43, 660, 147, 35, 376, 939, 60, 941, 534, 683, 5, 0, 953, 16, 7, 49, 649, 595, 470}, - {15, 515, 700, 753, 13, 1, 0, 23, 2, 33, 77, 4, 3, 51, 5, 102, 115, 10, 9, 341, 6, 7, 11, 342, 217, 12, 120, 180, 40, 317, 141, 8}, - {53, 27, 17, 161, 469, 378, 73, 527, 19, 136, 383, 250, 495, 56, 862, 26, 62, 84, 80, 106, 200, 4, 34, 14, 440, 297, 3, 128, 585, 5, 129, 123}, - {17, 45, 209, 106, 5, 207, 243, 454, 119, 255, 2, 263, 186, 290, 29, 3, 21, 62, 425, 61, 84, 32, 58, 56, 48, 408, 655, 136, 306, 14, 742, 227}, - {4, 152, 59, 452, 128, 79, 216, 11, 339, 471, 529, 188, 94, 77, 202, 12, 291, 33, 318, 377, 99, 51, 23, 5, 402, 349, 32, 474, 102, 13, 205, 111}, - {15, 515, 700, 753, 1, 0, 2, 13, 3, 5, 23, 4, 180, 51, 115, 9, 6, 12, 7, 8, 197, 33, 10, 961, 901, 77, 141, 752, 110, 22, 120, 341}, - {951, 752, 638, 811, 351, 642, 180, 253, 10, 341, 197, 901, 110, 873, 8, 244, 15, 352, 165, 898, 143, 515, 564, 762, 499, 55, 365, 700, 82, 753, 141, 854}, - {6, 262, 197, 350, 74, 26, 115, 509, 841, 583, 165, 38, 21, 13, 47, 50, 235, 19, 33, 324, 453, 4, 308, 196, 138, 99, 64, 903, 675, 1, 223, 130}, - {125, 165, 391, 23, 386, 221, 21, 13, 558, 457, 51, 867, 197, 115, 401, 758, 77, 97, 308, 791, 7, 180, 48, 120, 963, 451, 743, 89, 603, 134, 403, 450}, - {1, 14, 2, 5, 16, 46, 7, 38, 58, 24, 50, 0, 69, 48, 35, 67, 54, 18, 12, 75, 21, 45, 513, 155, 430, 37, 270, 9, 61, 163, 223, 32}, - {23, 13, 51, 0, 12, 15, 4, 1, 115, 2, 515, 453, 10, 457, 5, 3, 202, 21, 165, 700, 403, 11, 37, 64, 77, 401, 9, 197, 753, 59, 475, 99}, - {129, 84, 17, 56, 27, 495, 19, 548, 80, 123, 162, 378, 3, 504, 161, 469, 618, 73, 40, 53, 4, 26, 205, 184, 106, 183, 62, 6, 257, 128, 862, 12}, - {28, 9, 22, 49, 109, 1, 67, 0, 39, 55, 168, 158, 83, 36, 35, 86, 420, 194, 185, 159, 95, 105, 69, 208, 272, 103, 50, 114, 2, 254, 169, 30}, - {242, 391, 8, 456, 116, 13, 23, 492, 341, 165, 867, 51, 499, 457, 479, 638, 338, 509, 719, 10, 1, 642, 417, 762, 401, 93, 206, 268, 901, 569, 22, 197}, - {211, 162, 248, 130, 57, 4, 41, 556, 507, 266, 183, 152, 305, 361, 11, 129, 62, 229, 38, 471, 514, 313, 157, 300, 377, 3, 440, 128, 123, 328, 339, 59}, - {7, 92, 97, 16, 298, 140, 60, 126, 14, 35, 279, 314, 232, 246, 43, 230, 508, 173, 71, 107, 423, 24, 150, 779, 20, 189, 66, 18, 607, 21, 0, 653}, - {15, 515, 700, 753, 1, 0, 2, 13, 23, 5, 3, 180, 51, 901, 6, 4, 7, 12, 9, 115, 8, 457, 165, 82, 120, 197, 10, 64, 141, 341, 22, 117}, - {0, 18, 403, 25, 523, 74, 6, 24, 42, 91, 22, 102, 13, 51, 49, 193, 475, 681, 95, 85, 730, 64, 899, 397, 273, 750, 247, 673, 32, 805, 757, 288}, - {56, 0, 18, 65, 33, 554, 84, 343, 64, 6, 90, 561, 22, 19, 899, 108, 27, 63, 289, 475, 240, 467, 370, 32, 233, 214, 24, 123, 95, 287, 28, 194}, - {31, 98, 127, 9, 0, 44, 293, 105, 395, 299, 49, 242, 28, 22, 599, 116, 1, 284, 276, 125, 456, 685, 763, 159, 272, 623, 23, 935, 393, 144, 201, 137}, - {1, 5, 2, 14, 38, 46, 50, 48, 21, 7, 58, 45, 270, 61, 155, 171, 0, 290, 69, 32, 29, 54, 67, 16, 24, 666, 663, 17, 37, 75, 502, 52}, - {23, 51, 13, 453, 457, 12, 719, 4, 15, 99, 401, 2, 961, 3, 11, 730, 475, 515, 0, 1, 165, 115, 629, 700, 14, 17, 403, 40, 5, 33, 37, 64}, - {968, 967, 966, 965, 964, 963, 962, 961, 960, 959, 958, 957, 956, 955, 954, 953, - 952, 951, 950, 949, 948, 947, 946, 945, 944, 943, 942, 941, 940, 939, 938, 937}, - {2, 1, 14, 29, 67, 103, 6, 46, 52, 75, 24, 133, 38, 218, 83, 309, 36, 108, 70, 114, 96, 5, 238, 74, 25, 26, 220, 236, 65, 50, 69, 87}, - {7, 71, 16, 92, 24, 60, 14, 97, 150, 140, 35, 189, 149, 298, 18, 230, 43, 508, 2, 423, 69, 0, 38, 314, 66, 279, 399, 517, 251, 20, 232, 273}, - {23, 1, 120, 51, 13, 202, 77, 141, 260, 21, 15, 5, 128, 82, 2, 450, 269, 165, 102, 318, 48, 32, 137, 515, 125, 64, 12, 115, 351, 180, 33, 7}, - {77, 13, 33, 23, 64, 51, 4, 102, 141, 128, 40, 1, 2, 202, 0, 6, 177, 115, 137, 15, 59, 10, 11, 7, 269, 22, 515, 180, 318, 3, 700, 95}, - {101, 9, 18, 363, 264, 520, 411, 604, 676, 682, 905, 271, 16, 821, 167, 0, 621, 364, 39, 100, 121, 118, 166, 781, 647, 252, 1, 848, 447, 265, 404, 60}, - {144, 203, 326, 382, 166, 418, 93, 88, 96, 822, 1, 141, 859, 77, 744, 438, 110, 269, 921, 367, 521, 274, 100, 39, 494, 120, 403, 473, 217, 576, 13, 291}, - {13, 21, 180, 125, 5, 23, 191, 32, 18, 16, 146, 199, 115, 24, 165, 118, 0, 225, 22, 1, 60, 197, 64, 901, 375, 241, 48, 12, 408, 71, 522, 818}, - {15, 515, 700, 753, 13, 0, 23, 8, 1, 51, 82, 102, 2, 33, 4, 9, 180, 165, 5, 77, 10, 110, 12, 197, 120, 260, 18, 326, 351, 403, 22, 457}, - {33, 77, 102, 64, 13, 23, 128, 51, 141, 202, 1, 40, 0, 2, 117, 10, 15, 4, 6, 318, 269, 134, 22, 515, 180, 115, 177, 153, 137, 196, 3, 700}, - {174, 544, 104, 525, 74, 0, 151, 25, 6, 624, 29, 66, 2, 636, 81, 45, 204, 177, 64, 416, 7, 644, 5, 138, 222, 319, 355, 77, 22, 122, 789, 216}, - {141, 304, 372, 352, 291, 947, 177, 269, 128, 954, 77, 349, 217, 202, 64, 318, 498, 437, 102, 864, 86, 13, 115, 180, 137, 5, 210, 197, 32, 950, 678, 7}, - {161, 200, 53, 17, 714, 27, 34, 73, 472, 62, 585, 56, 440, 383, 136, 78, 527, 19, 4, 3, 106, 361, 14, 250, 80, 514, 377, 84, 322, 390, 862, 548}, - {32, 76, 72, 21, 38, 14, 89, 54, 12, 37, 2, 241, 5, 428, 17, 1, 181, 221, 350, 45, 3, 4, 449, 90, 148, 179, 99, 292, 794, 770, 477, 46}, - {33, 23, 128, 64, 141, 13, 77, 51, 102, 202, 2, 15, 1, 3, 40, 10, 5, 153, 269, 515, 165, 0, 117, 196, 180, 318, 6, 700, 137, 134, 120, 22}, - {96, 137, 30, 0, 9, 39, 840, 202, 669, 406, 141, 530, 613, 1, 180, 88, 22, 160, 679, 576, 28, 403, 31, 219, 49, 228, 829, 100, 36, 15, 10, 856}, - {180, 141, 352, 1, 15, 752, 115, 0, 217, 365, 2, 515, 13, 901, 341, 317, 23, 4, 197, 700, 269, 5, 3, 31, 753, 244, 21, 165, 253, 202, 51, 44}, - {1, 2, 67, 0, 28, 50, 83, 65, 14, 46, 103, 114, 24, 38, 36, 9, 69, 5, 18, 7, 22, 133, 55, 218, 16, 124, 29, 54, 96, 160, 12, 480}, - {180, 115, 352, 317, 365, 217, 752, 901, 141, 15, 341, 1, 515, 253, 700, 0, 753, 873, 2, 197, 31, 137, 165, 244, 4, 120, 160, 44, 98, 5, 202, 3}, - {5, 32, 347, 49, 13, 21, 95, 713, 23, 1, 77, 33, 60, 64, 107, 4, 126, 928, 296, 850, 0, 241, 197, 102, 652, 195, 180, 534, 165, 153, 379, 10}, - {341, 180, 365, 901, 317, 115, 15, 752, 515, 700, 217, 873, 753, 82, 0, 110, 197, 141, 951, 165, 1, 564, 13, 351, 253, 12, 10, 3, 2, 4, 308, 244}, - {17, 45, 21, 3, 106, 5, 155, 38, 227, 32, 2, 209, 62, 54, 12, 243, 14, 181, 552, 587, 46, 540, 207, 794, 37, 48, 430, 119, 255, 221, 770, 29}, - {16, 24, 35, 18, 7, 0, 50, 1, 9, 14, 75, 69, 2, 5, 12, 21, 60, 13, 67, 71, 23, 48, 10, 108, 223, 181, 189, 103, 46, 64, 92, 51}, - {127, 13, 98, 165, 308, 23, 286, 293, 258, 51, 219, 395, 197, 115, 301, 401, 31, 391, 22, 105, 457, 170, 239, 276, 55, 338, 629, 116, 180, 479, 509, 569}, - {539, 213, 748, 840, 957, 669, 30, 466, 88, 217, 144, 251, 863, 190, 137, 93, - 230, 228, 679, 352, 317, 203, 617, 321, 258, 530, 160, 219, 96, 831, 816, 689}, - {5, 48, 1, 21, 2, 14, 0, 36, 12, 38, 32, 54, 430, 181, 50, 270, 72, 99, 281, 45, 17, 10, 46, 22, 37, 218, 67, 3, 290, 76, 23, 51}, - {13, 23, 0, 4, 33, 51, 2, 115, 141, 1, 77, 217, 180, 10, 9, 317, 3, 102, 11, 5, 15, 197, 7, 202, 22, 165, 40, 64, 515, 6, 341, 31}, - {13, 15, 117, 515, 23, 12, 37, 134, 165, 700, 38, 54, 457, 753, 51, 64, 153, 197, 14, 10, 33, 82, 961, 0, 99, 89, 115, 719, 141, 3, 4, 1}, - {5, 21, 2, 3, 1, 32, 14, 12, 48, 17, 0, 10, 51, 23, 38, 22, 4, 72, 13, 54, 36, 45, 137, 76, 99, 114, 86, 37, 11, 64, 540, 430}, - {202, 128, 77, 318, 291, 33, 269, 102, 275, 141, 494, 342, 40, 678, 0, 177, 20, 210, 402, 7, 4, 5, 137, 6, 13, 450, 403, 32, 49, 120, 23, 22}, - {1, 2, 24, 14, 67, 46, 69, 50, 38, 103, 16, 18, 75, 35, 83, 29, 52, 96, 5, 108, 0, 7, 54, 71, 149, 394, 236, 309, 70, 133, 220, 58}, - {15, 515, 1, 700, 0, 2, 753, 13, 23, 5, 180, 3, 51, 4, 165, 457, 12, 197, 115, 6, 7, 21, 9, 141, 8, 901, 33, 82, 120, 77, 10, 110}, - {0, 28, 65, 14, 67, 2, 124, 24, 1, 9, 7, 69, 55, 154, 36, 16, 46, 114, 175, 35, 83, 22, 429, 18, 109, 149, 68, 189, 108, 336, 251, 133}, - {56, 162, 403, 3, 129, 775, 99, 161, 17, 40, 527, 33, 880, 4, 14, 128, 475, 12, 548, 23, 102, 202, 361, 117, 34, 184, 383, 200, 183, 196, 64, 53}, - {151, 2, 29, 58, 112, 45, 186, 113, 5, 70, 52, 1, 311, 6, 315, 66, 61, 7, 74, 27, 631, 17, 80, 87, 287, 243, 209, 227, 14, 491, 19, 869}, - {6, 1, 74, 2, 75, 29, 25, 66, 26, 70, 52, 138, 67, 324, 357, 42, 19, 220, 14, 85, 87, 108, 38, 451, 309, 103, 24, 69, 380, 135, 114, 65}, - {15, 515, 700, 13, 23, 0, 1, 120, 753, 51, 180, 2, 260, 202, 5, 141, 77, 102, 9, 450, 115, 21, 197, 165, 7, 137, 110, 33, 12, 269, 901, 4}, - {5, 45, 17, 2, 14, 46, 48, 38, 181, 50, 155, 3, 186, 54, 61, 29, 21, 227, 281, 80, 540, 106, 12, 400, 52, 1, 58, 32, 328, 171, 209, 487}, - {16, 18, 265, 121, 158, 35, 60, 9, 39, 7, 329, 105, 252, 68, 24, 1, 132, 167, 159, 22, 0, 49, 286, 101, 21, 146, 23, 327, 120, 709, 5, 14}, - {108, 467, 283, 56, 389, 650, 123, 412, 33, 177, 899, 475, 216, 453, 269, 349, 619, 65, 51, 730, 403, 670, 23, 196, 523, 128, 84, 13, 401, 789, 503, 543}, - {514, 3, 11, 377, 328, 4, 361, 507, 57, 403, 14, 880, 130, 485, 176, 215, 236, 38, 152, 102, 211, 56, 62, 757, 54, 585, 300, 556, 34, 555, 40, 229}, - {3, 555, 62, 266, 130, 99, 507, 139, 514, 12, 152, 229, 215, 305, 57, 40, 440, 33, 403, 471, 38, 56, 475, 14, 361, 313, 775, 328, 196, 548, 123, 23}, - {120, 202, 318, 15, 77, 13, 1, 450, 33, 269, 515, 260, 5, 128, 494, 51, 23, 700, 102, 141, 40, 753, 326, 403, 817, 137, 523, 21, 177, 922, 342, 7}, - {15, 1, 515, 23, 0, 13, 700, 2, 51, 753, 180, 5, 165, 21, 197, 12, 3, 120, 115, 4, 141, 6, 9, 7, 457, 33, 386, 202, 82, 8, 31, 341}, - {15, 180, 515, 82, 351, 700, 10, 317, 753, 115, 217, 365, 141, 898, 33, 901, 13, 23, 110, 854, 752, 77, 1, 197, 4, 341, 143, 36, 64, 352, 102, 9}, - {104, 289, 66, 707, 214, 90, 712, 64, 97, 173, 20, 0, 414, 194, 874, 43, 32, 7, 568, 560, 65, 38, 426, 312, 715, 192, 376, 74, 835, 5, 324, 147}, - {84, 56, 0, 554, 63, 65, 453, 249, 123, 643, 18, 26, 847, 475, 511, 403, 416, 561, 524, 289, 370, 73, 9, 19, 45, 42, 719, 194, 27, 467, 33, 730}, - {21, 346, 13, 350, 308, 826, 197, 101, 352, 68, 570, 0, 165, 23, 9, 841, 115, 100, 509, 694, 221, 230, 35, 217, 569, 88, 124, 749, 1, 777, 212, 154}, - {16, 92, 7, 24, 60, 18, 35, 140, 126, 14, 50, 71, 46, 330, 2, 75, 246, 5, 121, 267, 571, 1, 230, 309, 220, 0, 9, 64, 146, 236, 54, 108}, - {82, 15, 515, 898, 365, 700, 180, 33, 341, 753, 77, 901, 10, 115, 55, 351, 21, 5, 1, 4, 13, 102, 36, 217, 2, 165, 752, 120, 197, 117, 11, 317}, - {16, 24, 35, 18, 69, 71, 140, 1, 103, 7, 189, 68, 0, 50, 9, 108, 2, 133, 60, 267, 230, 46, 149, 67, 167, 118, 92, 14, 75, 21, 191, 38}, - {60, 71, 16, 18, 7, 20, 43, 118, 35, 68, 375, 28, 608, 0, 175, 566, 154, 92, 14, 149, 628, 33, 22, 13, 2, 10, 279, 23, 107, 356, 55, 117}, - {187, 258, 871, 295, 201, 434, 219, 224, 489, 384, 268, 110, 261, 839, 44, 699, - 93, 116, 36, 131, 141, 228, 144, 160, 940, 567, 244, 406, 137, 574, 98, 253}, - {66, 7, 97, 172, 192, 712, 232, 324, 204, 74, 43, 448, 387, 426, 568, 20, 526, 107, 104, 135, 356, 729, 173, 0, 22, 5, 32, 95, 2, 64, 500, 560}, - {15, 515, 700, 753, 1, 4, 0, 341, 13, 3, 134, 2, 5, 33, 11, 77, 12, 10, 23, 197, 365, 901, 7, 40, 217, 32, 21, 6, 51, 180, 961, 37}, - {0, 28, 24, 9, 35, 65, 16, 124, 68, 55, 109, 154, 7, 39, 22, 149, 158, 14, 175, 1, 49, 252, 18, 71, 2, 168, 289, 419, 108, 420, 67, 101}, - {7, 16, 14, 92, 2, 46, 140, 24, 220, 35, 38, 60, 75, 1, 50, 18, 87, 54, 5, 126, 29, 52, 278, 262, 314, 107, 71, 21, 172, 135, 330, 394}, - {7, 92, 16, 14, 172, 126, 2, 60, 140, 35, 135, 314, 278, 46, 24, 38, 232, 107, 330, 66, 5, 18, 150, 246, 230, 97, 52, 1, 121, 563, 279, 21}, - {6, 26, 235, 53, 297, 436, 27, 19, 25, 73, 113, 445, 90, 214, 65, 42, 64, 289, 250, 611, 624, 32, 45, 648, 614, 17, 85, 491, 34, 122, 200, 416}, - {352, 141, 1, 217, 854, 752, 351, 180, 244, 36, 110, 661, 82, 258, 816, 160, 295, 219, 567, 224, 230, 269, 922, 144, 260, 268, 93, 201, 137, 116, 489, 202}, - {16, 60, 35, 18, 126, 107, 68, 191, 92, 121, 7, 14, 598, 20, 493, 279, 167, 446, 118, 0, 28, 43, 463, 55, 24, 212, 375, 566, 9, 150, 575, 21}, - {15, 1, 515, 2, 4, 13, 0, 700, 3, 5, 23, 753, 341, 77, 51, 115, 33, 11, 180, 10, 197, 141, 6, 165, 7, 901, 102, 40, 9, 202, 217, 12}, - {23, 51, 13, 202, 21, 5, 1, 120, 15, 137, 128, 125, 32, 2, 12, 141, 33, 165, 64, 515, 403, 318, 700, 48, 180, 7, 6, 450, 115, 523, 475, 260}, - {131, 716, 224, 371, 219, 187, 737, 616, 385, 254, 9, 98, 105, 924, 31, 258, 836, 39, 127, 578, 49, 916, 44, 761, 272, 137, 944, 159, 0, 242, 442, 22}, - {15, 515, 700, 1, 753, 2, 5, 0, 4, 13, 3, 180, 11, 141, 197, 10, 341, 217, 33, 134, 165, 6, 77, 7, 317, 12, 352, 64, 365, 32, 102, 40}, - {66, 74, 7, 173, 174, 29, 192, 2, 222, 20, 226, 43, 353, 52, 712, 6, 0, 138, 500, 204, 97, 145, 64, 104, 426, 673, 355, 90, 25, 5, 65, 87}, - {5, 259, 786, 534, 590, 493, 279, 49, 13, 581, 465, 21, 929, 35, 941, 132, 147, 32, 23, 612, 362, 626, 107, 121, 178, 0, 146, 61, 48, 939, 10, 18}, - {2, 14, 16, 7, 278, 69, 135, 140, 46, 24, 267, 35, 92, 38, 1, 189, 29, 52, 309, 60, 66, 75, 71, 172, 74, 357, 18, 87, 67, 6, 230, 5}, - {165, 13, 308, 197, 391, 23, 401, 15, 51, 457, 180, 509, 115, 569, 3, 629, 961, 719, 34, 758, 317, 734, 14, 29, 46, 2, 17, 901, 38, 453, 5, 217}, - {1, 22, 2, 14, 0, 28, 7, 168, 67, 49, 65, 24, 36, 95, 5, 105, 55, 35, 12, 46, 69, 16, 114, 159, 194, 50, 10, 9, 158, 83, 164, 109}, - {34, 453, 3, 196, 130, 14, 322, 11, 47, 51, 377, 236, 361, 4, 730, 153, 514, 711, 57, 440, 62, 17, 161, 108, 176, 59, 485, 56, 162, 412, 202, 117}, - {18, 16, 21, 23, 48, 13, 24, 35, 121, 5, 156, 60, 51, 1, 7, 132, 141, 221, 163, 115, 0, 271, 447, 340, 363, 202, 125, 71, 2, 781, 22, 698}, - {165, 13, 457, 23, 197, 961, 629, 569, 341, 41, 12, 38, 401, 901, 54, 51, 115, 17, 15, 509, 421, 37, 62, 45, 719, 57, 32, 328, 117, 758, 157, 99}, - {2, 1, 77, 141, 33, 64, 3, 102, 0, 23, 13, 5, 128, 10, 6, 15, 180, 202, 269, 40, 51, 515, 7, 165, 137, 117, 318, 4, 700, 153, 197, 352}, - {68, 212, 0, 124, 101, 9, 154, 16, 562, 191, 21, 149, 65, 24, 35, 1, 118, 167, 818, 350, 520, 100, 722, 841, 264, 71, 13, 302, 478, 23, 375, 346}, - {98, 23, 48, 598, 13, 293, 541, 21, 125, 121, 51, 807, 0, 31, 35, 259, 126, 7, 386, 1, 223, 783, 10, 107, 199, 20, 221, 144, 342, 963, 49, 64}, - {21, 13, 5, 586, 1, 23, 167, 48, 33, 781, 647, 49, 165, 18, 51, 271, 77, 32, 761, 118, 0, 82, 391, 22, 146, 141, 459, 31, 197, 156, 115, 4}, - {2, 1, 5, 61, 29, 7, 58, 45, 14, 6, 425, 32, 70, 52, 290, 738, 207, 21, 72, 112, 66, 76, 655, 17, 186, 46, 64, 263, 38, 0, 128, 87}, - {39, 265, 9, 100, 1, 333, 363, 101, 18, 411, 447, 254, 166, 310, 31, 98, 264, 30, 639, 404, 156, 286, 16, 93, 593, 203, 272, 682, 0, 905, 44, 821}, - {6, 2, 1, 19, 29, 51, 26, 108, 25, 74, 5, 23, 14, 114, 13, 386, 133, 103, 42, 66, 453, 70, 309, 138, 719, 324, 65, 38, 64, 96, 52, 75}, - {20, 43, 356, 107, 49, 858, 595, 7, 414, 359, 0, 5, 392, 319, 97, 612, 422, 819, 14, 376, 173, 246, 22, 470, 147, 427, 230, 92, 197, 33, 683, 95}, - {0, 9, 68, 35, 65, 67, 114, 101, 28, 1, 124, 175, 336, 69, 154, 103, 83, 24, 189, 133, 39, 16, 50, 7, 2, 149, 55, 251, 18, 345, 230, 36}, - {23, 13, 51, 15, 0, 1, 515, 115, 165, 2, 5, 12, 700, 202, 4, 21, 141, 457, 753, 197, 10, 3, 180, 120, 32, 9, 318, 11, 453, 64, 6, 269}, - {121, 195, 60, 16, 126, 107, 98, 271, 146, 407, 132, 35, 1, 167, 199, 223, 493, 191, 279, 20, 18, 5, 43, 7, 21, 92, 48, 393, 0, 362, 212, 467}, - {31, 44, 299, 116, 393, 144, 492, 456, 268, 22, 105, 0, 367, 918, 384, 434, 127, 489, 98, 9, 963, 125, 242, 948, 1, 28, 206, 49, 36, 51, 93, 293}, - {23, 13, 457, 51, 165, 401, 719, 758, 197, 453, 961, 629, 308, 14, 15, 12, 730, 3, 386, 569, 391, 29, 739, 515, 34, 828, 832, 901, 115, 514, 670, 341}, - {105, 36, 131, 22, 180, 115, 341, 127, 169, 1, 9, 31, 64, 98, 44, 365, 317, 141, 272, 143, 160, 55, 219, 86, 197, 776, 239, 187, 0, 535, 13, 752}, - {1, 6, 2, 14, 66, 25, 29, 5, 108, 67, 65, 114, 19, 38, 26, 52, 74, 7, 24, 18, 69, 86, 36, 388, 64, 51, 17, 83, 23, 46, 42, 75}, - {51, 386, 23, 453, 719, 13, 730, 6, 457, 670, 758, 19, 401, 165, 2, 475, 47, 26, 899, 14, 108, 17, 1, 5, 197, 29, 894, 754, 236, 74, 27, 285}, - {252, 18, 9, 101, 121, 16, 132, 0, 419, 167, 364, 60, 604, 35, 265, 363, 146, 271, 39, 158, 68, 109, 28, 329, 848, 24, 647, 907, 682, 159, 212, 55}, - {283, 503, 128, 432, 26, 193, 63, 269, 789, 529, 102, 122, 389, 275, 678, 6, 25, 318, 445, 4, 342, 27, 573, 605, 177, 862, 643, 291, 216, 57, 235, 59}, - {2, 1, 29, 75, 69, 52, 14, 6, 46, 74, 87, 7, 220, 226, 278, 38, 135, 66, 267, 70, 16, 262, 25, 24, 380, 324, 357, 140, 67, 394, 97, 222}, - {97, 298, 69, 7, 66, 140, 189, 24, 16, 267, 172, 423, 60, 150, 14, 314, 92, 71, 81, 501, 43, 35, 74, 6, 517, 232, 149, 607, 83, 330, 18, 2}, - {475, 421, 403, 899, 51, 805, 523, 958, 453, 817, 23, 615, 401, 801, 120, 326, 202, 670, 494, 730, 450, 386, 115, 629, 260, 576, 77, 365, 569, 0, 165, 13}, - {7, 20, 14, 128, 77, 97, 112, 202, 2, 177, 16, 415, 269, 318, 275, 66, 107, 43, 141, 414, 135, 38, 307, 10, 58, 0, 6, 291, 32, 5, 4, 40}, - {24, 14, 7, 0, 2, 1, 22, 28, 16, 65, 168, 124, 35, 67, 108, 109, 18, 49, 10, 149, 69, 158, 5, 95, 289, 12, 55, 6, 36, 71, 46, 21}, - {26, 80, 27, 73, 122, 25, 19, 17, 6, 42, 684, 209, 445, 573, 667, 106, 45, 690, 4, 611, 255, 680, 297, 495, 65, 59, 128, 119, 483, 113, 64, 53}, - {107, 259, 362, 376, 465, 20, 470, 147, 595, 534, 612, 683, 660, 43, 5, 49, 581, 0, 858, 35, 427, 246, 97, 786, 178, 356, 14, 21, 142, 878, 7, 279}, - {131, 30, 228, 190, 856, 406, 224, 88, 219, 530, 863, 613, 778, 274, 944, 816, 187, 39, 100, 160, 258, 31, 44, 93, 1, 321, 539, 36, 871, 137, 435, 531}, - {113, 6, 311, 25, 45, 491, 80, 611, 27, 26, 209, 667, 17, 73, 122, 42, 684, 396, 19, 85, 106, 5, 614, 4, 2, 255, 151, 29, 1, 64, 648, 61}, - {15, 515, 700, 753, 0, 1, 23, 51, 120, 2, 13, 82, 5, 260, 9, 4, 341, 77, 180, 115, 141, 10, 7, 12, 450, 8, 202, 901, 197, 351, 165, 93}, - {219, 127, 98, 258, 395, 421, 924, 293, 242, 201, 697, 105, 276, 51, 308, 23, 453, 272, 401, 944, 512, 137, 13, 31, 284, 567, 386, 365, 116, 131, 964, 125}, - {15, 180, 352, 141, 515, 752, 217, 82, 1, 317, 854, 700, 351, 753, 115, 341, 110, 13, 260, 120, 21, 36, 33, 898, 23, 10, 5, 365, 4, 160, 901, 137}, - {129, 123, 17, 257, 162, 184, 205, 249, 183, 769, 5, 80, 3, 4, 229, 130, 119, 45, 90, 99, 618, 106, 57, 497, 12, 128, 2, 84, 59, 152, 27, 40}, - {33, 102, 23, 77, 64, 128, 51, 13, 0, 202, 10, 141, 40, 15, 1, 22, 117, 137, 2, 86, 4, 403, 269, 153, 515, 196, 65, 11, 700, 115, 99, 5}, - {7, 14, 2, 16, 172, 107, 46, 92, 5, 135, 35, 202, 294, 87, 38, 232, 29, 97, 20, 21, 24, 1, 60, 220, 66, 43, 12, 0, 126, 52, 54, 70}, - {403, 576, 615, 523, 475, 326, 805, 817, 494, 421, 51, 202, 120, 450, 137, 453, 23, 859, 260, 401, 402, 77, 33, 670, 0, 958, 15, 197, 386, 515, 165, 480}, - {141, 352, 217, 137, 0, 180, 202, 349, 9, 269, 23, 51, 115, 291, 77, 372, 13, 317, 120, 752, 365, 351, 93, 22, 2, 341, 64, 10, 82, 854, 28, 18}, - {1, 23, 13, 51, 202, 141, 5, 165, 21, 15, 120, 180, 64, 2, 197, 125, 33, 102, 12, 7, 137, 515, 48, 128, 269, 318, 93, 700, 0, 403, 9, 4}, - {25, 151, 6, 145, 122, 29, 174, 45, 113, 74, 4, 665, 42, 138, 2, 614, 416, 287, 19, 348, 746, 0, 66, 26, 1, 7, 64, 243, 311, 396, 81, 624}, - {30, 190, 254, 166, 100, 382, 731, 829, 88, 131, 264, 795, 9, 93, 625, 274, 438, 1, 578, 613, 716, 31, 44, 39, 530, 36, 616, 921, 265, 203, 160, 77}, - {132, 5, 21, 13, 1, 23, 32, 195, 379, 687, 156, 121, 626, 296, 48, 70, 850, 146, 51, 82, 883, 771, 35, 49, 652, 407, 60, 4, 260, 0, 845, 33}, - {9, 254, 0, 49, 272, 131, 39, 159, 688, 101, 105, 578, 518, 158, 286, 28, 327, 333, 68, 224, 252, 219, 344, 16, 22, 1, 716, 31, 30, 228, 24, 890}, - {16, 7, 35, 60, 18, 20, 14, 68, 9, 0, 28, 118, 43, 92, 126, 55, 107, 2, 101, 154, 24, 71, 5, 202, 121, 109, 22, 252, 21, 97, 1, 621}, - {15, 515, 700, 753, 13, 1, 341, 2, 0, 4, 3, 5, 11, 23, 10, 33, 117, 12, 901, 197, 6, 134, 77, 8, 165, 317, 21, 365, 217, 7, 17, 40}, - {78, 19, 444, 47, 26, 390, 27, 453, 130, 813, 108, 730, 711, 65, 412, 122, 51, 680, 113, 235, 690, 196, 630, 283, 128, 236, 14, 64, 73, 53, 200, 445}, - {2, 7, 29, 5, 61, 6, 45, 1, 66, 113, 112, 14, 52, 315, 738, 128, 32, 151, 74, 16, 20, 64, 70, 21, 592, 0, 25, 4, 425, 43, 491, 222}, - {145, 112, 74, 66, 6, 29, 26, 70, 19, 396, 25, 87, 2, 287, 135, 151, 138, 222, 5, 226, 42, 122, 7, 307, 1, 644, 45, 58, 113, 651, 635, 632}, - {92, 16, 7, 60, 126, 24, 140, 35, 14, 232, 18, 121, 246, 71, 46, 267, 172, 150, 107, 314, 132, 146, 230, 2, 278, 108, 330, 199, 236, 5, 38, 572}, - {13, 115, 197, 538, 569, 341, 98, 55, 165, 127, 365, 762, 219, 286, 844, 23, 170, 206, 734, 638, 535, 901, 169, 253, 629, 0, 873, 509, 180, 10, 332, 258}, - {58, 151, 74, 53, 287, 27, 29, 396, 6, 70, 2, 73, 5, 52, 112, 26, 651, 1, 297, 113, 17, 75, 19, 45, 334, 445, 145, 34, 315, 549, 436, 331}, - {214, 289, 90, 874, 104, 751, 64, 65, 312, 835, 204, 249, 750, 194, 74, 81, 875, 32, 519, 288, 348, 0, 174, 247, 636, 715, 138, 192, 784, 6, 524, 280}, - {9, 39, 28, 35, 30, 0, 166, 49, 1, 175, 439, 158, 64, 346, 36, 101, 67, 364, 86, 88, 274, 100, 168, 55, 23, 10, 420, 22, 190, 141, 505, 180}, - {341, 901, 15, 515, 700, 753, 1, 365, 10, 0, 569, 180, 2, 197, 115, 31, 165, 3, 5, 4, 44, 22, 317, 13, 9, 951, 23, 253, 116, 143, 762, 93}, - {120, 202, 77, 450, 260, 15, 128, 318, 102, 515, 494, 13, 817, 700, 269, 5, 403, 51, 1, 33, 23, 753, 82, 326, 141, 342, 291, 137, 21, 523, 351, 32}, - {13, 115, 241, 64, 180, 32, 125, 197, 165, 4, 118, 22, 21, 23, 16, 247, 237, 28, 225, 191, 95, 141, 167, 5, 0, 341, 288, 35, 459, 18, 177, 24}, - {16, 24, 35, 14, 1, 2, 7, 69, 18, 46, 60, 50, 267, 140, 71, 189, 108, 38, 75, 92, 0, 5, 9, 230, 67, 21, 309, 335, 54, 236, 394, 220}, - {15, 515, 700, 753, 898, 180, 901, 341, 197, 638, 10, 165, 33, 1, 115, 4, 77, 365, 317, 13, 102, 217, 117, 0, 5, 2, 253, 3, 82, 569, 21, 752}, - {193, 523, 18, 84, 56, 730, 233, 65, 4, 817, 90, 33, 643, 403, 91, 511, 453, 240, 59, 11, 214, 51, 719, 196, 153, 475, 32, 123, 64, 847, 102, 561}, - {112, 29, 151, 2, 74, 6, 66, 7, 222, 145, 287, 45, 5, 624, 52, 25, 113, 416, 58, 122, 19, 70, 186, 204, 4, 87, 644, 549, 337, 884, 32, 0}, - {13, 0, 23, 2, 1, 15, 33, 3, 77, 515, 141, 5, 4, 217, 10, 51, 64, 180, 700, 115, 6, 117, 11, 7, 753, 40, 102, 165, 197, 22, 317, 153}, - {28, 0, 1, 67, 65, 9, 2, 114, 83, 69, 103, 50, 36, 22, 55, 24, 46, 14, 124, 109, 35, 7, 16, 38, 133, 160, 389, 323, 18, 12, 154, 5}, - {121, 132, 18, 167, 271, 146, 101, 363, 621, 9, 411, 647, 16, 354, 520, 60, 212, 932, 1, 806, 55, 0, 195, 446, 68, 35, 31, 364, 777, 252, 407, 118}, - {26, 6, 85, 396, 122, 624, 25, 19, 42, 445, 64, 648, 573, 416, 174, 680, 665, 214, 45, 348, 90, 65, 194, 145, 113, 881, 138, 289, 112, 436, 297, 544}, - {16, 146, 18, 92, 24, 199, 60, 71, 121, 126, 35, 108, 156, 953, 271, 674, 132, 7, 32, 640, 360, 246, 649, 118, 21, 95, 5, 517, 14, 9, 1, 314}, - {51, 13, 23, 453, 475, 730, 719, 15, 457, 403, 64, 115, 33, 95, 4, 523, 3, 12, 21, 6, 899, 102, 5, 128, 401, 202, 11, 141, 308, 515, 22, 125}, - {151, 396, 6, 53, 27, 113, 58, 26, 73, 112, 74, 287, 45, 29, 297, 19, 145, 70, 138, 445, 315, 436, 34, 2, 17, 573, 5, 61, 549, 491, 1, 80}, - {223, 1, 888, 774, 260, 98, 269, 385, 349, 202, 96, 141, 421, 622, 730, 863, 318, 697, 87, 453, 393, 418, 922, 834, 751, 5, 163, 335, 120, 291, 352, 30}, - {16, 60, 92, 35, 126, 121, 7, 150, 246, 18, 107, 1, 598, 24, 167, 195, 14, 97, 71, 279, 98, 441, 191, 199, 517, 146, 356, 223, 298, 271, 230, 0}, - {22, 1, 105, 28, 239, 170, 0, 55, 95, 31, 36, 301, 2, 320, 98, 127, 9, 49, 44, 64, 35, 67, 10, 86, 5, 12, 109, 23, 168, 13, 21, 312}, - {2, 6, 5, 207, 292, 76, 1, 119, 45, 32, 17, 29, 61, 306, 790, 58, 240, 106, 14, 64, 214, 151, 476, 710, 7, 72, 84, 128, 4, 179, 70, 25}, - {51, 23, 221, 254, 115, 13, 438, 530, 125, 48, 21, 39, 541, 960, 386, 49, 1, 613, 15, 840, 228, 308, 627, 131, 688, 401, 5, 326, 421, 158, 165, 83}, - {1, 5, 2, 0, 12, 22, 21, 36, 10, 14, 48, 86, 23, 13, 32, 54, 3, 4, 28, 65, 51, 50, 137, 37, 208, 114, 9, 38, 17, 7, 281, 202}, - {363, 23, 447, 182, 296, 340, 1, 93, 698, 478, 379, 156, 284, 144, 18, 269, 21, 98, 141, 70, 668, 411, 664, 658, 110, 914, 67, 937, 180, 691, 335, 291}, - {17, 32, 45, 498, 41, 115, 180, 197, 106, 62, 54, 38, 546, 165, 13, 155, 468, 509, 341, 243, 241, 217, 542, 15, 57, 536, 428, 51, 117, 721, 292, 129}, - {32, 95, 64, 246, 22, 92, 180, 13, 5, 652, 125, 241, 638, 237, 7, 49, 4, 126, 21, 115, 197, 296, 888, 316, 0, 165, 774, 23, 16, 392, 1, 534}, - {15, 515, 700, 753, 33, 341, 13, 217, 4, 141, 77, 23, 180, 317, 1, 10, 102, 351, 82, 115, 40, 5, 854, 21, 137, 11, 352, 901, 365, 117, 197, 0}, - {15, 120, 1, 82, 93, 217, 515, 260, 77, 141, 13, 110, 700, 351, 352, 23, 180, 753, 21, 854, 202, 317, 64, 349, 269, 51, 165, 137, 5, 128, 291, 36}, - {13, 23, 51, 141, 77, 0, 33, 4, 115, 64, 2, 10, 102, 202, 217, 128, 1, 177, 269, 11, 7, 22, 6, 21, 32, 9, 180, 40, 15, 3, 165, 318}, - {478, 264, 1, 520, 98, 724, 9, 682, 223, 664, 21, 759, 13, 772, 604, 100, 23, 363, 411, 48, 821, 5, 0, 905, 909, 447, 31, 265, 88, 101, 166, 39}, - {20, 29, 7, 2, 77, 416, 6, 128, 33, 5, 0, 113, 104, 32, 43, 13, 491, 66, 23, 21, 102, 51, 74, 210, 202, 525, 64, 318, 10, 81, 174, 14}, - {2, 1, 5, 14, 7, 58, 61, 29, 45, 290, 46, 38, 52, 21, 32, 270, 6, 592, 425, 0, 75, 155, 16, 48, 17, 50, 72, 70, 207, 24, 263, 663}, - {80, 6, 17, 209, 106, 26, 483, 113, 19, 469, 255, 25, 378, 27, 495, 833, 45, 64, 161, 2, 61, 667, 76, 742, 32, 90, 445, 5, 814, 65, 887, 119}, - {98, 223, 393, 1, 354, 834, 195, 791, 447, 697, 284, 293, 360, 541, 781, 156, 51, 807, 18, 664, 421, 411, 163, 668, 48, 31, 591, 765, 883, 386, 948, 23}, - {679, 141, 816, 36, 93, 406, 876, 144, 228, 137, 1, 180, 669, 21, 332, 251, 5, 269, 116, 187, 96, 351, 202, 752, 317, 64, 203, 831, 574, 466, 855, 345}, - {15, 515, 700, 13, 1, 753, 2, 0, 23, 341, 3, 5, 4, 10, 51, 11, 33, 165, 6, 7, 115, 197, 12, 64, 180, 153, 217, 77, 9, 569, 901, 317}, - {13, 23, 202, 51, 5, 21, 403, 15, 120, 64, 1, 450, 128, 141, 12, 523, 33, 165, 494, 125, 2, 515, 269, 7, 48, 102, 318, 95, 260, 180, 453, 197}, - {16, 18, 24, 60, 71, 92, 146, 246, 199, 35, 140, 7, 9, 118, 121, 108, 167, 230, 126, 132, 0, 640, 156, 14, 68, 133, 267, 360, 649, 271, 64, 55}, - {269, 141, 678, 177, 202, 77, 128, 318, 33, 947, 40, 120, 291, 349, 102, 137, 64, 352, 210, 864, 461, 498, 13, 342, 196, 23, 275, 450, 954, 0, 205, 111}, - {16, 24, 92, 18, 71, 60, 35, 7, 108, 191, 167, 246, 140, 14, 126, 21, 1, 68, 150, 118, 149, 388, 399, 9, 273, 0, 121, 796, 230, 48, 212, 517}, - {2, 14, 1, 29, 46, 75, 52, 70, 69, 171, 38, 7, 58, 163, 16, 5, 24, 220, 67, 112, 223, 54, 50, 409, 155, 35, 267, 186, 151, 334, 394, 140}, - {9, 252, 100, 265, 166, 39, 88, 404, 329, 0, 1, 520, 382, 812, 101, 593, 264, 274, 604, 676, 30, 118, 68, 553, 18, 664, 363, 23, 639, 865, 21, 411}, - {16, 18, 35, 24, 0, 60, 158, 7, 22, 68, 14, 49, 109, 159, 55, 9, 28, 71, 2, 10, 5, 105, 1, 118, 329, 13, 344, 23, 92, 20, 21, 126}, - {15, 13, 515, 700, 23, 0, 753, 1, 51, 2, 4, 10, 77, 5, 3, 197, 115, 165, 961, 202, 9, 457, 180, 12, 141, 22, 33, 120, 6, 11, 318, 31}, - {160, 93, 251, 137, 317, 1, 180, 36, 120, 217, 345, 752, 617, 352, 332, 10, 96, 531, 498, 318, 365, 202, 141, 269, 816, 341, 901, 679, 143, 35, 83, 968}, - {6, 25, 42, 128, 19, 59, 122, 4, 85, 26, 611, 27, 269, 233, 45, 0, 343, 91, 318, 80, 11, 177, 283, 73, 33, 614, 2, 77, 64, 138, 445, 216}, - {95, 64, 74, 7, 32, 81, 51, 204, 0, 20, 237, 65, 56, 38, 91, 23, 207, 180, 347, 343, 29, 6, 511, 52, 49, 10, 25, 18, 554, 370, 14, 312}, - {202, 120, 326, 260, 450, 817, 494, 318, 137, 403, 128, 77, 523, 553, 859, 5, 704, 1, 15, 23, 13, 576, 7, 16, 615, 51, 682, 291, 515, 0, 21, 234}, - {20, 43, 107, 356, 362, 126, 595, 92, 359, 7, 422, 319, 493, 16, 858, 5, 392, 246, 414, 683, 60, 0, 35, 945, 441, 21, 259, 819, 49, 97, 279, 173}, - {25, 42, 6, 77, 33, 102, 0, 122, 4, 690, 29, 483, 210, 27, 21, 19, 2, 300, 18, 648, 680, 119, 117, 59, 1, 10, 342, 12, 26, 153, 91, 684}, - {31, 44, 299, 116, 125, 242, 456, 599, 22, 393, 0, 144, 492, 28, 268, 1, 9, 963, 301, 105, 367, 36, 127, 170, 384, 434, 206, 98, 918, 10, 13, 93}, - {410, 521, 686, 367, 662, 88, 335, 321, 201, 96, 98, 772, 144, 1, 934, 921, 443, 435, 284, 274, 264, 551, 120, 897, 44, 100, 33, 225, 744, 418, 909, 960}, - {142, 178, 878, 234, 132, 786, 195, 202, 77, 416, 147, 929, 146, 522, 167, 259, 687, 639, 450, 271, 626, 481, 590, 5, 198, 212, 771, 49, 0, 465, 315, 427}, - {254, 39, 131, 9, 272, 0, 578, 716, 310, 224, 30, 49, 105, 827, 518, 829, 166, 333, 616, 228, 613, 846, 101, 219, 1, 31, 890, 98, 159, 938, 252, 100}, - {230, 699, 854, 473, 450, 351, 831, 137, 855, 217, 352, 704, 800, 202, 251, 498, - 160, 144, 206, 203, 317, 201, 253, 752, 418, 141, 1, 332, 82, 180, 443, 36}, - {403, 202, 475, 453, 494, 23, 51, 77, 318, 402, 13, 33, 128, 102, 137, 141, 120, 342, 269, 0, 450, 4, 899, 576, 40, 421, 275, 117, 217, 177, 196, 64}, - {23, 44, 98, 182, 291, 144, 116, 39, 110, 141, 96, 82, 905, 70, 367, 264, 125, 93, 77, 411, 120, 1, 658, 202, 100, 415, 107, 363, 197, 30, 447, 105}, - {15, 515, 1, 13, 700, 23, 77, 120, 0, 753, 51, 180, 202, 141, 260, 5, 21, 115, 2, 137, 128, 9, 450, 197, 365, 269, 12, 326, 110, 102, 318, 7}, - {0, 32, 18, 95, 207, 577, 193, 29, 61, 104, 64, 784, 715, 102, 693, 887, 81, 91, 583, 671, 403, 5, 52, 474, 397, 180, 138, 49, 37, 344, 38, 263}, - {0, 101, 9, 68, 252, 16, 100, 39, 166, 364, 124, 24, 154, 265, 212, 88, 18, 35, 329, 419, 28, 118, 71, 30, 65, 158, 191, 55, 1, 694, 21, 676}, - {16, 24, 191, 18, 35, 71, 167, 118, 149, 68, 212, 9, 0, 1, 21, 108, 101, 92, 60, 375, 302, 7, 589, 755, 124, 674, 350, 48, 562, 246, 13, 363}, - {2, 14, 69, 24, 1, 67, 46, 16, 38, 103, 29, 267, 7, 35, 189, 135, 278, 71, 108, 18, 83, 309, 52, 6, 149, 388, 75, 236, 60, 0, 150, 66}, - {13, 1, 23, 0, 4, 2, 51, 15, 180, 33, 3, 115, 5, 515, 141, 10, 77, 700, 11, 9, 197, 341, 202, 165, 217, 102, 22, 7, 753, 317, 365, 6}, - {447, 1, 698, 411, 31, 363, 98, 5, 919, 4, 156, 125, 759, 691, 13, 64, 459, 354, 44, 21, 48, 293, 30, 914, 478, 225, 82, 120, 2, 922, 848, 839}, - {854, 82, 351, 217, 141, 180, 352, 15, 515, 752, 1, 700, 317, 898, 753, 244, 10, 21, 922, 115, 77, 36, 4, 260, 64, 110, 372, 13, 5, 365, 120, 11}, - {0, 1, 4, 13, 5, 2, 82, 33, 3, 120, 10, 23, 9, 11, 77, 260, 21, 102, 8, 31, 40, 6, 351, 51, 64, 450, 22, 117, 93, 110, 7, 457}, - {51, 13, 403, 23, 12, 475, 1, 2, 21, 5, 453, 523, 115, 202, 817, 7, 0, 99, 3, 6, 450, 120, 494, 64, 22, 95, 49, 899, 10, 37, 32, 141}, - {180, 752, 352, 141, 498, 864, 317, 217, 9, 0, 115, 237, 230, 39, 30, 197, 83, 1, 930, 64, 35, 365, 372, 13, 579, 88, 702, 36, 101, 901, 482, 21}, - {16, 24, 0, 7, 22, 18, 28, 35, 14, 158, 71, 2, 109, 60, 1, 168, 49, 154, 124, 68, 10, 55, 92, 118, 159, 9, 5, 747, 95, 105, 65, 6}, - {15, 515, 700, 753, 0, 23, 1, 13, 341, 51, 120, 77, 141, 4, 137, 33, 260, 82, 202, 9, 180, 5, 351, 2, 291, 10, 11, 901, 21, 115, 40, 128}, - {24, 68, 35, 149, 18, 16, 0, 7, 9, 14, 189, 108, 69, 65, 67, 1, 71, 2, 118, 28, 140, 101, 114, 336, 230, 124, 175, 133, 46, 55, 251, 154}, - {13, 308, 197, 115, 125, 9, 165, 237, 391, 23, 509, 569, 546, 28, 49, 629, 22, 338, 317, 254, 749, 180, 468, 159, 903, 386, 217, 352, 558, 39, 36, 734}, - {64, 90, 32, 217, 77, 4, 141, 216, 172, 312, 128, 13, 86, 33, 597, 147, 352, 95, 5, 115, 875, 22, 59, 11, 102, 14, 182, 437, 97, 177, 874, 707}, - {1, 22, 36, 0, 105, 28, 2, 67, 95, 49, 55, 5, 239, 12, 86, 9, 83, 170, 312, 64, 31, 21, 23, 10, 164, 50, 114, 159, 208, 13, 7, 320}, - {9, 18, 16, 0, 159, 105, 101, 252, 49, 310, 24, 68, 35, 39, 265, 272, 7, 1, 60, 28, 455, 890, 329, 557, 118, 286, 55, 137, 327, 167, 5, 13}, - {129, 123, 214, 249, 618, 17, 5, 257, 205, 184, 460, 76, 2, 162, 769, 245, 90, 106, 128, 45, 119, 1, 183, 4, 3, 12, 179, 64, 6, 229, 99, 209}, - {51, 453, 719, 457, 23, 13, 730, 899, 475, 386, 4, 15, 11, 12, 670, 196, 515, 523, 961, 401, 153, 3, 700, 99, 753, 117, 403, 32, 120, 165, 57, 0}, - {173, 66, 192, 204, 20, 74, 104, 636, 7, 43, 289, 426, 825, 712, 560, 214, 81, 750, 65, 97, 707, 0, 90, 414, 64, 348, 32, 500, 22, 861, 95, 6}, - {13, 23, 1, 51, 5, 21, 141, 120, 202, 15, 165, 2, 515, 180, 12, 125, 0, 64, 82, 700, 197, 269, 32, 48, 260, 128, 115, 93, 9, 137, 33, 753}, - {200, 34, 322, 78, 472, 390, 27, 714, 19, 14, 136, 161, 453, 176, 236, 444, 59, 3, 62, 128, 108, 57, 283, 862, 73, 53, 47, 17, 412, 813, 4, 56}, - {33, 347, 66, 204, 426, 498, 56, 172, 97, 95, 5, 681, 546, 22, 10, 0, 135, 180, 4, 241, 19, 174, 6, 353, 263, 21, 7, 370, 42, 197, 27, 808}, - {131, 224, 219, 187, 385, 371, 258, 442, 254, 737, 31, 98, 836, 127, 924, 944, 44, 871, 908, 716, 39, 827, 201, 574, 116, 137, 36, 1, 276, 242, 578, 616}, - {1, 15, 2, 180, 4, 141, 13, 515, 0, 5, 3, 115, 700, 901, 341, 23, 217, 352, 753, 51, 197, 77, 317, 33, 365, 752, 165, 21, 6, 7, 269, 93}, - {370, 91, 718, 74, 81, 510, 397, 66, 636, 240, 355, 84, 138, 511, 18, 278, 6, 681, 701, 289, 90, 5, 214, 582, 64, 104, 0, 643, 192, 65, 750, 32}, - {15, 515, 700, 753, 13, 120, 1, 0, 165, 2, 197, 23, 260, 180, 4, 82, 51, 386, 8, 5, 12, 10, 3, 141, 351, 341, 326, 9, 450, 7, 64, 6}, - {32, 2, 76, 5, 1, 292, 72, 45, 476, 214, 21, 241, 29, 14, 17, 48, 129, 90, 179, 460, 464, 123, 290, 148, 519, 205, 3, 263, 249, 38, 710, 89}, - {13, 165, 115, 17, 197, 569, 23, 509, 457, 45, 32, 41, 106, 180, 62, 38, 659, 734, 155, 536, 341, 629, 961, 873, 587, 54, 431, 37, 391, 99, 405, 428}, - {68, 24, 35, 16, 0, 101, 9, 124, 154, 71, 149, 65, 18, 175, 28, 118, 7, 55, 302, 108, 92, 14, 22, 346, 1, 39, 429, 252, 375, 364, 10, 67}, - {0, 9, 1, 68, 230, 65, 35, 69, 83, 23, 101, 13, 141, 67, 217, 352, 21, 39, 16, 88, 28, 124, 212, 100, 115, 154, 51, 64, 30, 36, 10, 317}, - {100, 265, 88, 909, 410, 382, 812, 593, 1, 213, 321, 30, 252, 230, 352, 264, 9, 166, 689, 39, 676, 98, 21, 466, 724, 639, 478, 217, 13, 48, 553, 101}, - {113, 61, 198, 904, 43, 0, 5, 37, 899, 325, 20, 59, 33, 523, 204, 725, 817, 389, 470, 329, 222, 40, 174, 58, 22, 453, 690, 848, 122, 104, 788, 105}, - {16, 24, 141, 18, 7, 0, 71, 140, 35, 269, 75, 352, 12, 9, 108, 217, 5, 330, 60, 64, 199, 70, 22, 13, 486, 246, 318, 133, 65, 50, 23, 498}, - {271, 167, 121, 60, 18, 191, 146, 199, 16, 1, 446, 132, 575, 212, 463, 354, 126, 35, 598, 566, 727, 98, 107, 21, 608, 955, 640, 407, 5, 24, 223, 68}, - {15, 515, 115, 217, 700, 13, 317, 753, 141, 180, 33, 23, 110, 120, 4, 341, 82, 10, 1, 260, 365, 36, 64, 854, 351, 21, 51, 352, 137, 77, 40, 0}, - {173, 7, 97, 356, 43, 107, 20, 387, 729, 104, 426, 232, 560, 595, 359, 392, 414, 707, 885, 81, 5, 0, 66, 858, 612, 49, 861, 14, 22, 32, 819, 230}, - {15, 515, 700, 753, 13, 23, 51, 82, 0, 33, 165, 120, 196, 4, 1, 2, 197, 453, 260, 351, 180, 12, 40, 8, 386, 110, 5, 326, 9, 141, 217, 457}, - {9, 100, 120, 30, 77, 795, 137, 82, 202, 39, 264, 827, 578, 127, 0, 166, 373, 318, 18, 326, 141, 260, 1, 450, 731, 31, 33, 395, 217, 291, 341, 254}, - {14, 2, 67, 1, 24, 69, 0, 28, 65, 7, 46, 18, 114, 108, 36, 83, 38, 398, 9, 16, 124, 133, 103, 154, 50, 55, 22, 267, 29, 160, 35, 547}, - {14, 7, 69, 24, 66, 16, 2, 267, 189, 67, 71, 150, 140, 97, 18, 60, 172, 35, 6, 1, 38, 149, 388, 92, 83, 135, 108, 74, 462, 380, 29, 36}, - {15, 515, 700, 753, 1, 13, 2, 0, 4, 341, 5, 3, 23, 365, 11, 117, 180, 10, 12, 33, 134, 115, 77, 197, 217, 165, 6, 7, 317, 102, 21, 9}, - {1, 22, 0, 12, 5, 2, 36, 28, 21, 10, 86, 13, 23, 49, 128, 9, 95, 51, 55, 96, 208, 141, 48, 202, 4, 137, 37, 64, 105, 3, 50, 7}, - {605, 630, 63, 123, 736, 650, 65, 108, 444, 368, 561, 389, 19, 25, 42, 619, 122, 194, 183, 27, 53, 33, 84, 26, 297, 813, 114, 73, 256, 235, 249, 216}, - {127, 39, 9, 0, 31, 371, 98, 254, 1, 385, 395, 44, 30, 836, 187, 131, 100, 116, 284, 578, 299, 166, 28, 21, 737, 16, 276, 272, 23, 49, 137, 935}, - {2, 61, 6, 29, 45, 151, 1, 655, 7, 207, 32, 5, 112, 425, 17, 76, 833, 4, 14, 64, 58, 106, 119, 25, 113, 128, 72, 52, 70, 21, 292, 790}, - {2, 5, 17, 14, 3, 29, 23, 27, 13, 401, 46, 6, 51, 58, 1, 453, 45, 53, 34, 52, 133, 19, 236, 26, 181, 114, 99, 366, 151, 108, 218, 38}, - {31, 22, 170, 1, 301, 44, 127, 98, 36, 28, 55, 105, 239, 0, 338, 116, 512, 299, 293, 125, 86, 10, 242, 395, 2, 13, 9, 64, 841, 23, 95, 685}, - {1, 21, 2, 14, 5, 32, 48, 50, 38, 270, 46, 76, 290, 72, 45, 54, 17, 0, 155, 221, 263, 207, 37, 281, 430, 3, 89, 12, 181, 408, 36, 67}, - {17, 106, 119, 378, 84, 240, 62, 80, 383, 136, 306, 3, 56, 790, 742, 5, 207, 504, 64, 440, 32, 128, 45, 2, 123, 209, 14, 4, 61, 57, 297, 667}, - {13, 15, 1, 515, 23, 2, 0, 700, 4, 115, 3, 51, 5, 10, 753, 180, 33, 341, 217, 11, 165, 317, 365, 197, 6, 77, 40, 64, 22, 9, 7, 117}, - {772, 335, 96, 744, 1, 367, 662, 686, 652, 897, 303, 264, 521, 31, 225, 410, 141, 520, 260, 116, 64, 44, 321, 98, 144, 88, 919, 966, 340, 269, 349, 284}, - {1, 0, 5, 28, 36, 2, 12, 22, 83, 67, 65, 50, 24, 14, 9, 96, 21, 218, 18, 114, 48, 281, 54, 10, 7, 160, 181, 103, 37, 23, 133, 99}, - {25, 6, 145, 42, 138, 81, 174, 348, 525, 544, 26, 74, 85, 280, 287, 648, 746, 91, 66, 0, 29, 396, 204, 64, 636, 90, 122, 194, 355, 104, 65, 233}, - {16, 24, 0, 18, 28, 158, 7, 35, 49, 22, 68, 159, 55, 1, 14, 109, 105, 2, 9, 71, 65, 154, 124, 95, 424, 344, 60, 239, 118, 577, 21, 10}, - {352, 854, 699, 230, 93, 689, 137, 144, 217, 160, 251, 36, 669, 202, 351, 120, 617, 855, 752, 203, 332, 82, 450, 180, 141, 748, 831, 30, 258, 201, 1, 816}, - {15, 13, 515, 700, 1, 2, 0, 753, 23, 5, 4, 3, 51, 33, 10, 115, 11, 317, 217, 77, 180, 341, 117, 165, 6, 134, 197, 153, 64, 9, 102, 7}, - {104, 20, 43, 173, 66, 319, 0, 77, 202, 7, 198, 5, 97, 580, 355, 74, 2, 204, 174, 52, 712, 234, 426, 155, 102, 192, 32, 4, 500, 337, 226, 904}, - {13, 23, 15, 51, 1, 515, 0, 2, 5, 700, 141, 4, 753, 165, 115, 12, 3, 21, 457, 10, 180, 269, 32, 6, 197, 202, 9, 7, 120, 11, 77, 33}, - {15, 515, 700, 753, 0, 1, 13, 2, 23, 115, 4, 317, 8, 3, 5, 51, 9, 341, 10, 217, 22, 365, 33, 457, 6, 180, 77, 901, 197, 120, 18, 7}, - {15, 515, 700, 753, 1, 0, 2, 3, 4, 13, 5, 141, 23, 16, 82, 217, 457, 10, 365, 180, 9, 317, 51, 21, 269, 898, 64, 202, 11, 12, 318, 341}, - {2, 5, 1, 14, 50, 38, 29, 17, 114, 46, 133, 3, 45, 21, 58, 171, 181, 36, 218, 12, 6, 52, 0, 48, 137, 65, 361, 23, 155, 4, 285, 51}, - {0, 68, 9, 65, 101, 124, 35, 212, 16, 149, 154, 100, 24, 1, 114, 336, 67, 589, 252, 39, 71, 189, 69, 562, 18, 13, 30, 398, 118, 88, 265, 264}, - {1, 2, 14, 22, 0, 7, 67, 65, 28, 36, 24, 46, 168, 5, 86, 69, 38, 16, 49, 12, 289, 10, 194, 50, 83, 114, 95, 6, 18, 23, 55, 158}, - {13, 23, 15, 51, 515, 0, 700, 4, 1, 753, 2, 10, 115, 961, 457, 12, 33, 11, 3, 5, 197, 9, 165, 77, 102, 403, 453, 40, 64, 22, 37, 59}, - {15, 515, 700, 753, 0, 1, 2, 13, 23, 5, 51, 901, 8, 9, 180, 3, 7, 82, 4, 120, 12, 10, 719, 341, 6, 31, 141, 457, 197, 22, 115, 93}, - {100, 252, 88, 101, 0, 265, 9, 724, 48, 1, 21, 352, 213, 676, 410, 382, 321, 230, 30, 329, 593, 909, 39, 812, 553, 217, 23, 689, 520, 264, 166, 419}, - {2, 5, 1, 58, 171, 14, 46, 50, 29, 52, 45, 38, 186, 155, 67, 54, 151, 281, 334, 61, 48, 96, 17, 181, 103, 400, 502, 227, 21, 223, 12, 69}, - {23, 120, 13, 1, 202, 141, 51, 21, 165, 128, 260, 15, 5, 269, 137, 64, 33, 180, 82, 318, 93, 197, 77, 326, 515, 125, 110, 700, 450, 2, 32, 48}, - {341, 197, 10, 901, 13, 15, 8, 638, 569, 515, 479, 23, 180, 873, 700, 165, 143, 642, 0, 961, 753, 951, 1, 115, 509, 499, 116, 12, 498, 242, 82, 206}, - {15, 1, 23, 13, 515, 21, 120, 51, 2, 141, 202, 700, 5, 180, 165, 0, 753, 197, 12, 7, 33, 260, 352, 137, 269, 4, 82, 128, 48, 9, 110, 6}, - {2, 29, 50, 58, 1, 6, 5, 52, 14, 262, 17, 46, 27, 53, 151, 34, 171, 74, 324, 26, 38, 309, 45, 113, 19, 96, 287, 396, 223, 67, 73, 583}, - {13, 23, 141, 51, 4, 202, 0, 115, 77, 2, 33, 217, 5, 317, 180, 64, 10, 269, 3, 9, 15, 21, 1, 128, 102, 137, 318, 11, 352, 515, 22, 31}, - {1, 67, 0, 24, 50, 5, 14, 18, 16, 69, 2, 9, 103, 35, 83, 12, 96, 28, 54, 7, 58, 223, 21, 46, 281, 48, 65, 181, 22, 38, 36, 108}, - {13, 23, 141, 51, 77, 64, 202, 115, 33, 102, 128, 4, 0, 269, 10, 21, 217, 32, 180, 318, 9, 137, 2, 11, 22, 291, 7, 177, 16, 31, 165, 197}, - {317, 115, 180, 365, 873, 498, 217, 341, 13, 752, 482, 197, 569, 352, 1, 901, 36, 23, 457, 468, 165, 346, 546, 143, 509, 134, 579, 876, 868, 2, 332, 21}, - {184, 257, 205, 229, 152, 17, 57, 497, 266, 432, 452, 524, 5, 619, 381, 32, 4, 90, 2, 12, 313, 128, 45, 59, 245, 106, 3, 471, 129, 769, 339, 214}, - {13, 23, 1, 0, 15, 2, 4, 515, 51, 3, 10, 33, 5, 700, 115, 180, 753, 77, 11, 365, 341, 217, 9, 6, 197, 7, 102, 165, 317, 40, 22, 64}, - {626, 70, 771, 687, 379, 846, 767, 761, 518, 878, 82, 481, 31, 786, 49, 591, 178, 163, 407, 44, 87, 13, 845, 125, 590, 371, 195, 120, 98, 557, 937, 351}, - {264, 1, 410, 909, 772, 897, 686, 521, 335, 478, 98, 96, 691, 639, 100, 44, 284, 382, 31, 321, 744, 88, 914, 724, 662, 765, 223, 9, 682, 363, 0, 367}, - {13, 23, 1, 2, 0, 15, 51, 515, 5, 10, 4, 33, 115, 77, 180, 700, 3, 141, 217, 40, 6, 753, 317, 197, 64, 165, 7, 11, 102, 9, 341, 22}, - {141, 77, 13, 64, 269, 23, 115, 21, 318, 217, 5, 202, 102, 33, 137, 2, 15, 291, 177, 51, 48, 180, 32, 4, 515, 352, 128, 7, 0, 10, 96, 11}, - {13, 15, 23, 515, 51, 0, 700, 753, 1, 2, 4, 10, 33, 11, 961, 453, 115, 40, 457, 14, 12, 3, 9, 5, 165, 401, 197, 77, 22, 21, 64, 102}, - {1, 22, 0, 36, 2, 31, 5, 12, 13, 105, 28, 9, 49, 86, 141, 21, 23, 95, 128, 55, 44, 115, 170, 10, 164, 98, 180, 4, 137, 239, 83, 51}, - {100, 101, 88, 0, 252, 9, 265, 30, 21, 39, 759, 724, 213, 329, 321, 13, 419, 68, 562, 382, 676, 352, 694, 35, 553, 410, 1, 166, 909, 593, 230, 23}, - {539, 88, 30, 190, 321, 530, 840, 144, 669, 435, 957, 748, 778, 100, 96, 418, 203, 213, 1, 131, 410, 228, 466, 274, 36, 382, 219, 863, 613, 83, 822, 352}, - {7, 97, 92, 173, 298, 107, 43, 314, 232, 140, 16, 356, 20, 387, 729, 362, 126, 359, 246, 14, 230, 501, 426, 441, 0, 5, 560, 66, 104, 779, 35, 60}, - {2, 14, 7, 1, 58, 5, 46, 16, 38, 70, 75, 45, 24, 155, 29, 0, 21, 52, 61, 163, 220, 50, 69, 270, 35, 48, 32, 171, 18, 6, 64, 54}, - {447, 411, 363, 664, 647, 98, 621, 1, 354, 271, 223, 478, 18, 777, 781, 936, 360, 759, 167, 132, 121, 48, 21, 156, 9, 195, 118, 293, 23, 691, 13, 264}, - {2, 1, 14, 65, 36, 67, 0, 7, 46, 22, 69, 5, 38, 24, 28, 6, 83, 29, 86, 114, 168, 50, 124, 208, 12, 18, 108, 10, 194, 484, 103, 16}, - {421, 386, 51, 791, 730, 958, 165, 801, 23, 453, 697, 403, 615, 13, 221, 523, 24, 899, 401, 326, 551, 670, 576, 102, 18, 33, 125, 77, 566, 115, 203, 197}, - {104, 319, 422, 945, 0, 81, 20, 43, 715, 32, 784, 693, 879, 7, 397, 74, 306, 207, 52, 681, 671, 2, 61, 173, 6, 636, 904, 95, 887, 5, 18, 192}, - {2, 29, 1, 46, 14, 52, 70, 262, 6, 26, 50, 67, 75, 96, 309, 38, 103, 112, 58, 19, 5, 163, 145, 83, 74, 220, 223, 357, 24, 69, 331, 25}, - {786, 929, 590, 771, 687, 626, 941, 178, 465, 259, 70, 5, 13, 21, 35, 534, 107, 518, 132, 49, 878, 48, 146, 121, 379, 279, 31, 767, 147, 195, 108, 125}, - {5, 2, 186, 45, 17, 29, 48, 50, 14, 61, 46, 155, 400, 1, 227, 171, 52, 58, 38, 54, 430, 209, 80, 281, 3, 106, 536, 311, 181, 243, 21, 502}, - {0, 32, 64, 95, 817, 494, 342, 403, 207, 202, 194, 389, 453, 365, 312, 180, 316, 5, 690, 237, 848, 577, 450, 61, 102, 523, 475, 289, 49, 241, 65, 482}, - {23, 13, 51, 15, 202, 515, 1, 0, 2, 12, 115, 4, 700, 5, 165, 753, 77, 457, 21, 141, 128, 10, 3, 64, 403, 32, 197, 318, 9, 11, 33, 117}, - {119, 2, 6, 76, 5, 17, 45, 292, 306, 240, 32, 1, 19, 84, 64, 61, 4, 209, 710, 80, 26, 0, 106, 27, 214, 25, 128, 129, 29, 179, 3, 113}, - {15, 515, 700, 1, 753, 0, 13, 23, 180, 120, 51, 2, 5, 33, 165, 197, 9, 450, 7, 260, 115, 523, 4, 12, 202, 141, 82, 77, 21, 102, 8, 6}, - {6, 138, 74, 280, 222, 85, 66, 226, 25, 42, 87, 204, 64, 337, 29, 135, 95, 174, 235, 26, 145, 65, 19, 32, 792, 294, 112, 52, 256, 2, 5, 22}, - {39, 9, 0, 101, 333, 158, 49, 252, 310, 254, 272, 68, 16, 18, 159, 286, 344, 455, 30, 109, 627, 327, 24, 105, 419, 100, 364, 22, 35, 1, 329, 709}, - {21, 5, 32, 14, 2, 1, 38, 72, 76, 54, 17, 3, 48, 221, 270, 0, 45, 46, 12, 181, 37, 89, 36, 50, 540, 290, 430, 10, 4, 741, 99, 23}, - {120, 137, 202, 269, 141, 260, 318, 450, 922, 494, 77, 291, 82, 15, 5, 351, 128, 1, 515, 326, 64, 854, 700, 352, 342, 21, 753, 678, 349, 32, 523, 90}, - {16, 24, 68, 35, 71, 18, 149, 118, 191, 167, 9, 0, 212, 124, 65, 246, 7, 67, 140, 189, 399, 101, 133, 60, 1, 108, 267, 114, 69, 92, 695, 154}, - {28, 0, 9, 67, 1, 22, 109, 36, 55, 65, 194, 114, 39, 83, 49, 69, 2, 35, 103, 50, 158, 208, 86, 420, 168, 289, 505, 24, 7, 185, 5, 323}, - {147, 325, 198, 427, 142, 178, 202, 798, 5, 376, 20, 318, 259, 43, 120, 450, 77, 234, 534, 904, 470, 465, 878, 725, 329, 14, 315, 0, 260, 858, 70, 61}, - {28, 0, 65, 9, 109, 1, 55, 67, 35, 22, 24, 39, 289, 7, 175, 14, 114, 2, 158, 124, 420, 194, 68, 16, 336, 36, 49, 69, 168, 570, 154, 505}, - {141, 180, 13, 115, 1, 23, 4, 269, 2, 202, 0, 317, 217, 51, 15, 5, 21, 352, 77, 318, 3, 752, 197, 10, 165, 365, 137, 341, 9, 515, 33, 64}, - {15, 515, 700, 0, 753, 1, 2, 13, 23, 9, 51, 5, 4, 901, 33, 7, 8, 3, 12, 93, 180, 120, 197, 6, 82, 341, 10, 141, 22, 260, 457, 115}, - {6, 74, 66, 1, 25, 75, 324, 380, 278, 26, 138, 85, 135, 500, 87, 42, 220, 841, 97, 350, 29, 19, 70, 226, 38, 21, 52, 606, 235, 889, 2, 14}, - {13, 23, 51, 12, 4, 15, 453, 0, 457, 1, 403, 165, 115, 3, 11, 2, 64, 5, 401, 10, 515, 37, 202, 33, 40, 32, 99, 475, 197, 700, 308, 17}, - {788, 180, 5, 83, 693, 319, 314, 4, 32, 21, 17, 11, 817, 3, 510, 498, 33, 12, 24, 104, 814, 120, 64, 117, 306, 804, 523, 450, 288, 160, 102, 43}, - {15, 1, 515, 13, 2, 700, 23, 0, 4, 753, 3, 341, 5, 51, 33, 11, 10, 6, 77, 7, 115, 102, 180, 165, 141, 9, 197, 217, 901, 40, 12, 64}, - {101, 18, 9, 167, 520, 16, 0, 118, 60, 212, 604, 364, 694, 24, 55, 252, 68, 917, 264, 35, 1, 121, 146, 363, 39, 100, 806, 5, 21, 166, 191, 28}, - {13, 23, 0, 33, 51, 141, 77, 4, 64, 2, 115, 217, 9, 102, 7, 202, 21, 10, 180, 3, 15, 128, 5, 269, 6, 32, 11, 16, 165, 352, 22, 317}, - {66, 135, 97, 74, 172, 6, 278, 7, 204, 324, 138, 174, 29, 85, 2, 87, 25, 140, 92, 192, 52, 38, 802, 69, 448, 500, 808, 620, 22, 1, 280, 232}, - {2, 24, 69, 6, 97, 7, 1, 0, 14, 298, 423, 66, 67, 29, 150, 25, 189, 267, 124, 74, 607, 18, 36, 81, 172, 33, 83, 38, 52, 273, 71, 809}, - {0, 9, 158, 39, 68, 49, 109, 16, 24, 333, 35, 344, 101, 22, 159, 254, 272, 30, 124, 65, 28, 18, 793, 154, 310, 252, 327, 105, 627, 419, 286, 55}, - {15, 515, 700, 10, 753, 33, 77, 180, 4, 341, 1, 197, 13, 115, 365, 23, 901, 317, 5, 102, 11, 217, 165, 117, 141, 40, 2, 3, 253, 21, 134, 55}, - {100, 166, 382, 478, 265, 264, 88, 39, 98, 1, 404, 274, 9, 593, 724, 921, 639, 438, 363, 682, 411, 31, 30, 812, 96, 447, 821, 905, 252, 0, 223, 435}, - {19, 283, 436, 53, 297, 26, 813, 432, 27, 128, 42, 25, 390, 503, 122, 736, 73, 123, 605, 63, 389, 529, 630, 250, 690, 65, 381, 444, 6, 269, 108, 216}, - {33, 202, 13, 128, 494, 0, 51, 141, 269, 1, 4, 2, 102, 180, 15, 137, 65, 95, 6, 450, 77, 40, 117, 59, 457, 36, 196, 817, 134, 86, 49, 515}, - {18, 16, 60, 68, 101, 167, 191, 118, 35, 121, 9, 212, 55, 0, 126, 1, 24, 647, 199, 146, 520, 107, 628, 621, 363, 71, 21, 28, 346, 92, 806, 727}, - {352, 230, 217, 531, 160, 93, 36, 669, 748, 854, 689, 258, 137, 871, 728, 699, 752, 251, 574, 202, 373, 351, 228, 120, 717, 260, 144, 219, 268, 82, 816, 1}, - {15, 515, 700, 753, 13, 23, 0, 51, 8, 1, 4, 82, 165, 77, 110, 33, 10, 180, 5, 202, 11, 22, 120, 12, 9, 197, 115, 93, 403, 141, 40, 351}, - {0, 9, 101, 217, 35, 88, 352, 100, 39, 175, 30, 68, 562, 752, 13, 317, 252, 115, 180, 197, 64, 1, 83, 141, 65, 213, 165, 230, 194, 36, 28, 265}, - {32, 64, 5, 470, 288, 90, 21, 147, 0, 95, 356, 22, 20, 519, 835, 312, 819, 18, 247, 182, 11, 97, 13, 4, 387, 49, 43, 298, 316, 48, 107, 7}, - {16, 14, 24, 1, 7, 2, 35, 0, 5, 50, 18, 69, 46, 12, 58, 75, 9, 67, 70, 163, 21, 54, 38, 48, 223, 502, 281, 37, 140, 60, 28, 10}, - {18, 265, 9, 252, 39, 195, 354, 411, 1, 16, 132, 101, 121, 682, 167, 203, 5, 363, 146, 593, 35, 333, 21, 271, 60, 13, 100, 0, 156, 327, 7, 520}, - {4, 13, 1, 115, 141, 23, 2, 180, 5, 0, 51, 3, 217, 202, 77, 15, 33, 269, 341, 318, 317, 21, 165, 515, 11, 10, 197, 365, 9, 137, 64, 352}, - {7, 24, 16, 14, 71, 35, 18, 92, 140, 189, 108, 149, 68, 60, 69, 150, 2, 230, 97, 66, 0, 458, 67, 1, 65, 251, 38, 314, 388, 267, 36, 46}, - {1, 22, 31, 36, 0, 2, 44, 5, 141, 105, 180, 170, 12, 64, 13, 98, 86, 55, 23, 21, 28, 164, 115, 127, 10, 125, 128, 4, 9, 239, 352, 197}, - {66, 7, 97, 2, 192, 20, 52, 43, 135, 74, 560, 107, 104, 0, 750, 147, 414, 29, 580, 173, 324, 376, 226, 194, 77, 174, 204, 38, 356, 64, 16, 470}, - {0, 101, 9, 68, 35, 124, 24, 65, 39, 16, 252, 100, 154, 166, 28, 364, 149, 694, 30, 88, 55, 346, 1, 419, 71, 439, 265, 289, 22, 21, 175, 158}, - {39, 9, 100, 30, 127, 0, 737, 856, 31, 836, 827, 254, 98, 931, 166, 88, 93, 1, 44, 190, 131, 228, 120, 395, 625, 385, 863, 264, 219, 373, 110, 28}, - {5, 17, 2, 3, 21, 45, 14, 155, 48, 32, 38, 1, 328, 181, 186, 46, 23, 51, 12, 61, 227, 29, 106, 54, 99, 133, 62, 832, 13, 37, 514, 543}, - {131, 613, 30, 224, 228, 716, 274, 100, 827, 406, 219, 856, 39, 190, 31, 88, 1, 166, 9, 44, 829, 863, 931, 93, 0, 187, 625, 924, 127, 98, 137, 254}, - {352, 217, 64, 141, 752, 269, 180, 864, 437, 372, 954, 115, 498, 177, 77, 349, 317, 318, 579, 291, 947, 197, 247, 0, 23, 717, 237, 304, 128, 457, 776, 678}, - {141, 217, 180, 317, 352, 115, 15, 341, 1, 23, 13, 365, 515, 752, 2, 64, 0, 5, 498, 700, 372, 165, 51, 237, 753, 77, 244, 197, 137, 4, 21, 253}, - {5, 2, 17, 14, 1, 45, 3, 38, 21, 29, 181, 58, 46, 48, 50, 133, 114, 171, 61, 155, 32, 6, 186, 281, 361, 12, 36, 54, 4, 13, 52, 514}, - {6, 2, 119, 25, 790, 4, 45, 483, 655, 113, 1, 29, 76, 26, 32, 19, 887, 17, 128, 0, 292, 833, 59, 61, 106, 64, 77, 814, 14, 151, 84, 42}, - {13, 23, 2, 0, 51, 4, 1, 115, 141, 3, 5, 180, 33, 217, 77, 9, 202, 11, 7, 15, 10, 6, 317, 64, 21, 197, 515, 165, 102, 128, 22, 269}, - {13, 23, 51, 202, 21, 5, 1, 15, 141, 165, 120, 2, 115, 12, 32, 0, 515, 128, 318, 64, 125, 700, 4, 403, 197, 453, 180, 457, 3, 7, 10, 6}, - {9, 39, 31, 30, 0, 127, 1, 44, 100, 131, 98, 187, 385, 276, 88, 442, 219, 908, 254, 116, 49, 166, 935, 28, 201, 36, 141, 827, 137, 299, 284, 21}, - {22, 49, 28, 109, 9, 185, 105, 95, 1, 131, 159, 272, 36, 67, 86, 254, 39, 55, 35, 0, 505, 31, 83, 169, 208, 327, 286, 98, 168, 535, 312, 708}, - {5, 1, 2, 21, 0, 12, 48, 22, 10, 14, 36, 3, 32, 17, 23, 54, 86, 38, 4, 51, 13, 37, 137, 50, 65, 281, 114, 45, 28, 99, 58, 202}, - {141, 269, 352, 82, 217, 351, 180, 854, 372, 922, 752, 1, 15, 260, 317, 318, 515, 202, 64, 700, 120, 349, 954, 753, 77, 35, 67, 717, 898, 137, 365, 115}, - {144, 203, 613, 418, 326, 406, 96, 669, 137, 679, 1, 228, 494, 822, 840, 317, 36, 83, 855, 160, 817, 859, 856, 816, 217, 831, 345, 93, 876, 77, 44, 251}, - {15, 13, 515, 23, 700, 753, 51, 1, 33, 0, 202, 21, 2, 5, 180, 141, 120, 165, 217, 82, 12, 117, 4, 352, 269, 197, 115, 32, 3, 9, 134, 260}, - {13, 23, 115, 1, 0, 51, 4, 77, 2, 33, 15, 141, 10, 5, 341, 180, 515, 3, 217, 202, 9, 365, 317, 64, 700, 102, 11, 165, 197, 22, 753, 7}, - {531, 943, 373, 160, 728, 93, 206, 260, 261, 559, 964, 269, 717, 535, 332, 384, - 365, 295, 110, 533, 141, 10, 180, 352, 244, 137, 120, 55, 959, 564, 36, 253}, - {1, 31, 36, 170, 22, 55, 44, 10, 86, 64, 127, 0, 2, 98, 301, 164, 740, 338, 237, 143, 5, 125, 116, 13, 242, 141, 299, 180, 23, 169, 105, 12}, - {13, 23, 141, 77, 51, 4, 64, 32, 33, 202, 115, 269, 102, 128, 21, 0, 177, 180, 318, 90, 40, 10, 7, 5, 137, 15, 217, 352, 9, 291, 59, 22}, - {202, 120, 260, 318, 77, 15, 450, 269, 1, 82, 33, 23, 141, 13, 51, 515, 351, 128, 700, 5, 64, 326, 137, 21, 102, 110, 753, 494, 93, 523, 817, 165}, - {523, 899, 102, 33, 730, 15, 23, 403, 719, 117, 153, 13, 515, 51, 475, 4, 700, 5, 453, 817, 196, 753, 494, 40, 202, 120, 1, 2, 450, 457, 17, 421}, - {202, 403, 494, 450, 120, 817, 523, 475, 318, 453, 33, 402, 128, 77, 13, 51, 260, 576, 342, 102, 15, 23, 515, 4, 700, 5, 82, 753, 326, 210, 137, 615}, - {2, 29, 112, 66, 7, 52, 70, 151, 58, 87, 135, 5, 74, 226, 307, 6, 14, 186, 1, 45, 549, 172, 644, 25, 113, 287, 46, 155, 334, 64, 294, 97}, - {1, 77, 349, 291, 260, 120, 652, 102, 5, 39, 64, 269, 9, 33, 340, 342, 13, 98, 888, 698, 23, 296, 100, 318, 51, 202, 87, 137, 638, 128, 50, 850}, - {1, 13, 15, 2, 0, 4, 23, 515, 5, 141, 180, 3, 700, 341, 115, 51, 753, 269, 77, 901, 197, 352, 217, 33, 21, 11, 365, 6, 165, 202, 7, 317}, - {7, 14, 16, 2, 46, 5, 70, 58, 1, 38, 24, 35, 92, 163, 0, 75, 21, 18, 50, 54, 140, 12, 87, 220, 155, 69, 171, 23, 60, 9, 13, 307}, - {2, 29, 66, 226, 135, 7, 87, 74, 52, 278, 6, 75, 222, 220, 294, 70, 97, 1, 145, 25, 172, 262, 324, 38, 69, 112, 331, 92, 5, 14, 140, 26}, - {15, 515, 700, 753, 33, 77, 117, 4, 1, 102, 134, 40, 153, 11, 13, 196, 217, 21, 5, 51, 23, 115, 32, 3, 2, 202, 141, 137, 128, 291, 48, 177}, - {15, 217, 82, 515, 351, 141, 317, 1, 13, 700, 260, 77, 110, 120, 115, 854, 23, 753, 180, 51, 21, 36, 137, 922, 5, 64, 365, 352, 291, 202, 93, 341}, - {31, 190, 30, 373, 120, 110, 863, 88, 44, 127, 908, 856, 260, 318, 82, 98, 93, 187, 836, 717, 935, 39, 442, 131, 141, 254, 228, 219, 1, 968, 77, 116}, - {23, 13, 308, 9, 165, 115, 51, 21, 401, 125, 49, 39, 197, 391, 159, 254, 217, 743, 28, 438, 773, 629, 558, 386, 341, 95, 32, 317, 876, 679, 109, 166}, - {49, 5, 43, 165, 7, 0, 21, 104, 125, 22, 173, 422, 64, 13, 623, 102, 20, 18, 314, 95, 91, 141, 23, 31, 193, 51, 391, 900, 779, 558, 92, 232}, - {1, 4, 13, 2, 15, 0, 23, 515, 77, 3, 341, 33, 5, 700, 115, 51, 202, 753, 141, 180, 11, 10, 102, 217, 6, 901, 40, 7, 197, 318, 317, 365}, - {93, 843, 295, 120, 36, 160, 206, 261, 10, 137, 567, 110, 384, 141, 943, 268, 201, 332, 258, 55, 1, 180, 64, 116, 44, 144, 699, 203, 282, 31, 260, 373}, - {81, 7, 192, 426, 43, 173, 172, 104, 879, 91, 5, 712, 715, 526, 6, 97, 568, 95, 448, 66, 33, 861, 560, 32, 49, 20, 0, 636, 232, 825, 2, 22}, - {475, 403, 51, 453, 33, 102, 13, 23, 494, 202, 0, 196, 15, 77, 153, 18, 4, 117, 515, 450, 318, 22, 730, 128, 700, 421, 65, 753, 269, 402, 134, 817}, - {141, 269, 260, 318, 202, 120, 352, 349, 82, 351, 1, 5, 854, 137, 64, 291, 15, 922, 180, 851, 32, 77, 515, 372, 21, 700, 7, 217, 13, 947, 33, 753}, - {15, 515, 700, 753, 1, 13, 0, 2, 4, 23, 3, 5, 180, 115, 197, 12, 51, 165, 217, 10, 961, 9, 6, 141, 352, 21, 8, 7, 33, 77, 457, 120}, - {39, 166, 9, 30, 0, 101, 274, 404, 252, 333, 190, 100, 158, 438, 310, 88, 68, 265, 656, 21, 1, 530, 329, 344, 49, 539, 625, 254, 13, 131, 48, 419}, - {0, 1, 28, 9, 22, 12, 65, 83, 67, 36, 5, 2, 50, 55, 96, 109, 16, 13, 24, 23, 21, 238, 49, 18, 285, 160, 128, 39, 69, 114, 7, 323}, - {15, 515, 700, 1, 0, 753, 23, 2, 13, 51, 5, 180, 115, 6, 3, 9, 197, 12, 457, 120, 7, 165, 901, 82, 4, 21, 8, 141, 31, 33, 719, 341}, - {9, 39, 30, 0, 28, 166, 22, 49, 180, 1, 352, 35, 317, 158, 88, 141, 498, 131, 115, 345, 752, 128, 228, 217, 100, 83, 219, 930, 13, 251, 365, 36}, - {5, 61, 45, 2, 80, 29, 311, 209, 6, 17, 58, 1, 151, 106, 454, 667, 243, 70, 52, 496, 287, 592, 255, 738, 64, 74, 483, 14, 27, 32, 112, 19}, - {31, 125, 22, 44, 299, 456, 685, 242, 599, 116, 170, 28, 0, 1, 492, 393, 506, 144, 558, 10, 268, 301, 239, 23, 13, 36, 963, 367, 55, 206, 105, 95}, - {187, 258, 926, 574, 839, 93, 228, 860, 406, 219, 871, 160, 137, 531, 224, 116, 120, 902, 669, 201, 36, 131, 44, 144, 843, 533, 318, 384, 442, 1, 434, 268}, - {7, 107, 75, 16, 87, 9, 64, 177, 24, 18, 291, 77, 349, 141, 60, 232, 23, 0, 51, 269, 132, 14, 5, 21, 70, 32, 678, 112, 126, 121, 71, 947}, - {15, 515, 700, 753, 1, 0, 2, 13, 5, 3, 23, 180, 4, 115, 901, 51, 6, 8, 961, 9, 7, 10, 12, 82, 197, 22, 141, 341, 33, 120, 365, 457}, - {13, 23, 51, 1, 5, 202, 2, 12, 15, 21, 165, 141, 0, 115, 3, 4, 32, 515, 197, 10, 180, 318, 128, 120, 64, 700, 6, 7, 403, 269, 457, 137}, - {1, 2, 0, 77, 64, 3, 141, 13, 33, 15, 23, 10, 6, 102, 5, 515, 180, 4, 117, 7, 700, 165, 11, 217, 269, 40, 753, 115, 128, 17, 197, 134}, - {345, 531, 332, 269, 260, 317, 717, 752, 373, 351, 180, 352, 728, 82, 10, 365, 160, 533, 217, 143, 498, 251, 244, 93, 341, 901, 36, 1, 141, 898, 55, 864}, - {16, 7, 33, 189, 92, 77, 388, 60, 140, 35, 102, 24, 14, 1, 230, 21, 150, 117, 733, 314, 18, 915, 71, 13, 108, 134, 5, 64, 69, 2, 98, 22}, - {142, 202, 234, 178, 5, 786, 77, 49, 70, 0, 416, 450, 639, 878, 1, 48, 21, 929, 147, 259, 315, 455, 198, 120, 12, 481, 163, 113, 846, 329, 318, 22}, - {81, 715, 192, 0, 173, 712, 681, 104, 636, 91, 74, 20, 750, 370, 7, 718, 95, 879, 22, 43, 825, 560, 422, 64, 207, 49, 172, 18, 397, 10, 426, 319}, - {13, 23, 15, 51, 515, 0, 700, 753, 4, 1, 961, 2, 10, 115, 457, 11, 33, 453, 3, 5, 9, 40, 12, 197, 165, 77, 401, 475, 64, 102, 22, 569}, - {64, 297, 5, 445, 95, 61, 250, 311, 80, 34, 17, 312, 45, 2, 86, 472, 58, 14, 180, 53, 22, 151, 869, 738, 247, 237, 29, 1, 128, 165, 21, 288}, - {16, 24, 18, 71, 7, 35, 118, 92, 14, 154, 60, 68, 0, 149, 28, 302, 124, 150, 55, 175, 2, 9, 97, 1, 429, 20, 108, 273, 22, 65, 43, 126}, - {195, 360, 156, 771, 132, 163, 626, 687, 591, 371, 883, 146, 121, 846, 70, 586, 379, 13, 293, 98, 407, 48, 761, 296, 354, 18, 31, 1, 55, 49, 21, 105}, - {202, 13, 77, 23, 318, 33, 51, 0, 4, 141, 5, 21, 217, 32, 291, 102, 64, 128, 15, 10, 9, 494, 269, 137, 515, 403, 1, 31, 117, 700, 120, 317}, - {7, 192, 97, 81, 172, 66, 426, 173, 43, 715, 712, 232, 861, 879, 104, 330, 568, 298, 74, 893, 885, 526, 387, 825, 92, 140, 91, 14, 636, 6, 5, 448}, - {2, 1, 14, 6, 67, 7, 65, 69, 24, 36, 66, 124, 108, 83, 38, 29, 22, 86, 0, 18, 484, 5, 28, 46, 12, 10, 25, 302, 150, 16, 650, 74}, - {33, 77, 13, 202, 102, 4, 0, 23, 128, 51, 141, 64, 318, 22, 403, 269, 137, 10, 15, 40, 494, 117, 32, 59, 11, 153, 1, 21, 177, 196, 515, 115}, - {269, 141, 318, 77, 349, 291, 217, 202, 33, 15, 372, 304, 515, 22, 102, 177, 351, 700, 352, 120, 5, 137, 10, 317, 260, 753, 64, 851, 854, 403, 49, 21}, - {6, 74, 66, 85, 138, 25, 87, 42, 135, 26, 226, 222, 280, 29, 75, 500, 220, 278, 792, 70, 19, 2, 1, 294, 204, 64, 32, 145, 853, 112, 52, 174}, - {9, 0, 105, 39, 16, 18, 1, 101, 272, 31, 127, 98, 24, 518, 333, 252, 310, 28, 68, 737, 846, 371, 158, 916, 938, 49, 30, 7, 286, 35, 301, 455}, - {2, 1, 14, 67, 24, 46, 83, 108, 69, 29, 38, 103, 114, 36, 6, 133, 18, 0, 28, 7, 65, 52, 236, 75, 50, 398, 5, 309, 135, 16, 278, 160}, - {22, 1, 28, 105, 49, 95, 0, 2, 67, 55, 36, 239, 168, 159, 65, 35, 14, 170, 320, 164, 9, 7, 10, 5, 114, 12, 83, 64, 194, 109, 24, 301}, - {7, 66, 172, 97, 92, 140, 232, 568, 298, 14, 192, 314, 16, 380, 135, 324, 2, 330, 74, 38, 357, 448, 126, 69, 35, 5, 107, 6, 387, 60, 204, 572}, - {2, 29, 1, 14, 5, 6, 46, 133, 114, 50, 52, 26, 218, 108, 19, 13, 366, 236, 27, 45, 70, 17, 58, 23, 86, 51, 137, 65, 112, 38, 25, 12}, - {6, 1, 74, 25, 2, 26, 29, 66, 42, 19, 75, 14, 388, 67, 108, 70, 52, 85, 103, 65, 38, 138, 357, 133, 114, 594, 324, 516, 603, 96, 309, 69}, - {22, 9, 28, 1, 36, 49, 109, 105, 86, 95, 131, 31, 169, 39, 0, 141, 272, 159, 44, 55, 98, 180, 13, 30, 185, 115, 83, 128, 352, 137, 64, 208}, - {203, 822, 326, 23, 77, 859, 403, 494, 576, 39, 473, 182, 33, 1, 691, 100, 18, 217, 13, 817, 411, 447, 363, 102, 93, 966, 96, 478, 291, 704, 310, 120}, - {15, 515, 700, 753, 33, 77, 117, 4, 102, 134, 115, 153, 13, 1, 40, 217, 11, 196, 341, 2, 5, 3, 23, 317, 365, 0, 21, 291, 32, 51, 12, 569}, - {15, 515, 700, 753, 13, 0, 23, 1, 8, 82, 51, 165, 197, 120, 180, 2, 9, 33, 4, 110, 5, 12, 10, 260, 351, 386, 141, 7, 457, 475, 93, 901}, - {1, 23, 13, 15, 51, 0, 21, 2, 515, 5, 141, 180, 120, 165, 700, 202, 197, 4, 753, 12, 33, 9, 7, 82, 115, 93, 3, 352, 260, 6, 110, 48}, - {15, 515, 700, 753, 0, 1, 2, 5, 3, 4, 8, 13, 180, 341, 10, 23, 7, 6, 9, 51, 77, 197, 961, 115, 165, 82, 120, 31, 22, 202, 457, 217}, - {559, 661, 922, 564, 141, 533, 10, 317, 373, 110, 143, 269, 244, 260, 332, 261, - 93, 642, 752, 295, 351, 876, 531, 843, 180, 206, 728, 384, 352, 1, 434, 120}, - {15, 515, 1, 0, 700, 2, 13, 23, 753, 5, 51, 180, 3, 165, 12, 6, 197, 115, 4, 9, 7, 21, 719, 8, 457, 82, 141, 120, 33, 22, 901, 10}, - {198, 234, 0, 325, 5, 77, 202, 416, 20, 147, 32, 43, 639, 315, 49, 61, 450, 455, 142, 21, 113, 230, 22, 318, 725, 342, 207, 13, 95, 904, 494, 10}, - {447, 264, 363, 9, 411, 676, 682, 1, 156, 664, 821, 478, 166, 354, 812, 39, 100, 905, 382, 897, 98, 18, 759, 404, 31, 101, 724, 5, 265, 223, 88, 13}, - {24, 14, 69, 16, 35, 18, 2, 7, 108, 189, 71, 67, 267, 149, 1, 46, 68, 83, 38, 140, 0, 236, 251, 9, 388, 60, 133, 103, 65, 28, 29, 50}, - {16, 7, 35, 20, 14, 18, 109, 2, 43, 120, 107, 60, 1, 121, 326, 907, 553, 77, 13, 147, 23, 82, 68, 260, 0, 403, 5, 24, 202, 126, 265, 199}, - {30, 131, 187, 276, 31, 44, 613, 442, 39, 9, 190, 228, 1, 839, 116, 935, 908, 219, 127, 88, 244, 224, 110, 137, 93, 201, 98, 141, 36, 567, 0, 856}, - {98, 223, 1, 393, 812, 265, 100, 421, 593, 834, 697, 48, 51, 410, 791, 382, 21, 88, 31, 284, 9, 125, 96, 293, 230, 23, 213, 217, 656, 689, 541, 5}, - {98, 51, 127, 219, 616, 258, 105, 293, 395, 421, 924, 512, 31, 308, 23, 201, 116, 44, 301, 272, 763, 276, 125, 13, 453, 170, 401, 295, 261, 944, 115, 567}, - {253, 110, 951, 352, 811, 206, 332, 180, 141, 244, 282, 10, 854, 417, 642, 638, - 559, 752, 143, 911, 260, 55, 93, 533, 499, 498, 661, 120, 351, 959, 564, 341}, - {49, 9, 159, 254, 272, 158, 0, 131, 28, 39, 627, 105, 327, 286, 22, 518, 688, 578, 68, 347, 374, 101, 224, 424, 95, 35, 219, 24, 16, 364, 65, 344}, - {105, 22, 131, 272, 98, 286, 327, 109, 374, 239, 28, 95, 320, 219, 9, 224, 55, 127, 187, 36, 578, 169, 64, 185, 538, 1, 159, 10, 371, 634, 49, 616}, - {691, 478, 340, 1, 658, 914, 724, 363, 744, 698, 156, 772, 411, 296, 682, 447, 9, 284, 335, 98, 264, 303, 909, 21, 354, 410, 225, 13, 664, 686, 88, 919}, - {16, 24, 35, 18, 71, 7, 140, 108, 189, 267, 92, 60, 14, 230, 68, 69, 9, 1, 149, 46, 246, 191, 388, 167, 2, 0, 118, 236, 133, 21, 674, 5}, - {9, 0, 127, 31, 98, 371, 395, 39, 737, 49, 1, 44, 385, 272, 512, 28, 293, 242, 836, 761, 254, 299, 101, 16, 187, 22, 116, 158, 159, 131, 18, 21}, - {16, 18, 68, 0, 60, 35, 9, 101, 252, 28, 118, 24, 419, 55, 7, 109, 604, 71, 39, 121, 22, 364, 14, 158, 191, 167, 925, 126, 329, 21, 92, 49}, - {116, 268, 203, 93, 206, 692, 551, 31, 417, 940, 499, 8, 473, 44, 202, 523, 959, 0, 120, 137, 559, 22, 450, 403, 576, 10, 728, 299, 13, 326, 51, 1}, - {225, 459, 744, 1, 919, 914, 691, 330, 622, 21, 141, 223, 5, 284, 934, 335, 88, 538, 340, 82, 385, 839, 363, 120, 478, 98, 48, 30, 64, 32, 686, 166}, - {5, 1, 2, 0, 14, 36, 21, 281, 12, 48, 50, 67, 22, 28, 54, 83, 24, 218, 38, 10, 181, 9, 32, 18, 65, 58, 45, 114, 430, 17, 99, 37}, - {137, 450, 202, 704, 120, 260, 326, 318, 968, 269, 851, 403, 291, 77, 23, 141, 182, 310, 494, 373, 351, 457, 82, 890, 349, 110, 60, 128, 817, 678, 105, 96}, - {15, 515, 700, 753, 4, 33, 13, 23, 77, 5, 40, 11, 102, 93, 1, 21, 110, 51, 82, 117, 141, 2, 10, 8, 32, 64, 120, 31, 202, 3, 217, 115}, - {15, 13, 1, 23, 515, 0, 51, 2, 700, 5, 753, 21, 180, 141, 165, 3, 12, 115, 197, 4, 7, 6, 457, 9, 352, 202, 33, 8, 719, 120, 77, 341}, - {219, 127, 258, 98, 276, 201, 131, 395, 944, 293, 116, 284, 567, 31, 242, 105, 137, 935, 295, 44, 403, 860, 51, 224, 576, 456, 9, 371, 578, 475, 202, 512}, - {16, 7, 18, 35, 60, 0, 14, 20, 118, 28, 68, 22, 2, 24, 1, 92, 158, 107, 5, 49, 154, 126, 109, 12, 43, 10, 55, 6, 677, 71, 21, 168}, - {93, 728, 531, 160, 559, 373, 574, 120, 295, 860, 533, 269, 717, 260, 926, 902, - 258, 318, 36, 201, 261, 434, 851, 137, 617, 141, 187, 352, 843, 384, 332, 251}, - {28, 0, 1, 9, 22, 109, 83, 39, 49, 12, 36, 67, 55, 5, 96, 2, 128, 30, 158, 69, 21, 23, 160, 208, 35, 13, 65, 323, 50, 141, 194, 238}, - {23, 13, 51, 1, 5, 15, 141, 21, 0, 2, 165, 515, 202, 700, 12, 197, 180, 120, 32, 115, 4, 753, 64, 9, 7, 269, 6, 3, 125, 386, 48, 453}, - {5, 21, 13, 49, 14, 20, 7, 23, 43, 32, 1, 0, 652, 48, 713, 22, 38, 2, 16, 132, 955, 107, 12, 279, 24, 888, 197, 640, 70, 303, 18, 638}, - {9, 0, 28, 39, 1, 30, 35, 101, 22, 67, 83, 141, 49, 175, 36, 68, 55, 88, 13, 251, 10, 69, 23, 158, 180, 115, 64, 100, 217, 65, 345, 166}, - {260, 120, 82, 269, 5, 450, 351, 1, 202, 141, 854, 13, 77, 922, 32, 33, 137, 4, 23, 125, 291, 21, 15, 515, 165, 349, 177, 700, 318, 326, 180, 753}, - {121, 16, 18, 35, 363, 101, 60, 20, 107, 14, 68, 259, 621, 55, 604, 43, 7, 252, 9, 364, 126, 0, 167, 191, 5, 407, 132, 28, 199, 419, 146, 10}, - {13, 23, 51, 1, 15, 0, 2, 141, 5, 515, 12, 21, 700, 115, 165, 180, 4, 753, 3, 197, 202, 32, 9, 120, 7, 8, 6, 11, 37, 10, 457, 269}, - {201, 144, 206, 443, 418, 203, 435, 96, 335, 459, 187, 1, 88, 332, 330, 321, 269, 934, 30, 372, 822, 521, 268, 326, 44, 523, 382, 141, 410, 264, 494, 473}, - {31, 44, 276, 201, 116, 131, 284, 662, 567, 144, 9, 489, 98, 295, 268, 434, 0, 30, 137, 39, 93, 1, 187, 22, 219, 918, 110, 299, 141, 36, 224, 384}, - {520, 478, 664, 1, 264, 604, 9, 167, 777, 759, 411, 0, 806, 724, 48, 21, 101, 68, 647, 936, 363, 223, 118, 682, 410, 18, 100, 16, 252, 98, 265, 13}, - {23, 70, 21, 87, 60, 75, 120, 182, 163, 379, 92, 18, 7, 937, 71, 121, 446, 132, 24, 98, 931, 126, 107, 77, 795, 195, 115, 44, 411, 146, 51, 850}, - {39, 9, 0, 737, 127, 31, 846, 98, 1, 827, 105, 310, 371, 30, 254, 100, 44, 18, 395, 242, 272, 101, 385, 916, 836, 16, 265, 131, 938, 93, 166, 557}, - {279, 20, 43, 126, 107, 7, 92, 16, 356, 362, 60, 595, 246, 359, 598, 35, 0, 683, 939, 653, 121, 97, 125, 441, 399, 392, 150, 199, 48, 230, 14, 649}, - {206, 417, 93, 959, 499, 728, 8, 559, 120, 473, 137, 141, 10, 564, 31, 260, 44, 450, 203, 341, 253, 244, 373, 116, 143, 638, 268, 180, 352, 110, 318, 940}, - {259, 465, 147, 132, 590, 687, 534, 199, 581, 146, 941, 427, 107, 640, 279, 178, 121, 5, 195, 150, 522, 955, 198, 35, 786, 929, 798, 142, 1, 21, 325, 626}, - {523, 15, 120, 450, 202, 515, 403, 51, 817, 700, 13, 753, 23, 457, 33, 899, 128, 64, 730, 102, 494, 342, 115, 719, 453, 196, 49, 99, 318, 421, 308, 5}, - {141, 559, 10, 244, 365, 564, 661, 180, 253, 143, 752, 110, 55, 317, 533, 341, 901, 93, 373, 206, 535, 160, 82, 922, 260, 36, 531, 964, 352, 332, 261, 197}, - {219, 258, 98, 127, 276, 964, 943, 137, 843, 535, 201, 935, 131, 860, 261, 295, 284, 567, 206, 44, 116, 31, 253, 492, 203, 332, 160, 615, 36, 93, 55, 692}, - {0, 319, 422, 207, 945, 693, 577, 887, 32, 804, 95, 344, 104, 904, 61, 20, 5, 43, 7, 725, 113, 510, 306, 102, 49, 263, 153, 426, 33, 83, 22, 9}, - {1, 22, 0, 5, 12, 2, 36, 21, 28, 86, 49, 105, 9, 10, 23, 13, 141, 95, 31, 55, 128, 37, 51, 4, 83, 202, 3, 64, 96, 7, 32, 44}, - {15, 515, 13, 700, 1, 0, 753, 2, 23, 3, 4, 5, 51, 10, 115, 197, 6, 33, 12, 9, 165, 7, 8, 77, 11, 961, 180, 269, 141, 22, 120, 457}, - {15, 1, 23, 120, 77, 13, 515, 51, 141, 202, 700, 180, 110, 137, 260, 753, 326, 5, 128, 102, 0, 21, 2, 165, 269, 33, 197, 450, 318, 217, 93, 115}, - {15, 515, 1, 700, 0, 753, 13, 2, 23, 180, 51, 5, 120, 4, 9, 115, 197, 12, 7, 165, 21, 33, 6, 82, 3, 8, 523, 901, 31, 141, 457, 260}, - {16, 18, 24, 7, 92, 35, 60, 75, 9, 13, 71, 14, 0, 108, 50, 21, 126, 121, 1, 140, 23, 5, 132, 146, 2, 12, 128, 10, 64, 141, 70, 87}, - {180, 341, 901, 15, 515, 1, 365, 700, 0, 2, 197, 753, 115, 4, 10, 13, 752, 5, 3, 8, 165, 317, 141, 23, 143, 873, 44, 31, 569, 55, 93, 6}, - {9, 0, 175, 35, 101, 28, 39, 67, 68, 1, 65, 83, 30, 69, 364, 336, 22, 114, 55, 124, 194, 158, 100, 289, 252, 166, 64, 345, 103, 36, 50, 88}, - {64, 165, 180, 197, 115, 247, 217, 237, 21, 13, 32, 316, 22, 141, 352, 72, 288, 304, 95, 225, 76, 391, 386, 16, 468, 90, 49, 35, 365, 640, 372, 23}, - {15, 515, 700, 13, 753, 1, 0, 2, 23, 4, 5, 3, 115, 51, 141, 197, 12, 10, 180, 961, 7, 9, 21, 33, 217, 6, 8, 165, 457, 11, 77, 341}, - {132, 121, 199, 146, 60, 279, 493, 640, 407, 598, 126, 195, 534, 581, 955, 590, 107, 5, 150, 35, 522, 49, 259, 16, 18, 360, 156, 0, 147, 362, 21, 167}, - {0, 1, 28, 9, 22, 5, 36, 12, 65, 24, 67, 96, 2, 83, 18, 50, 114, 55, 21, 16, 7, 10, 23, 14, 13, 160, 137, 51, 48, 218, 103, 69}, - {93, 120, 957, 77, 30, 968, 459, 110, 137, 160, 613, 102, 202, 352, 373, 141, 31, 372, 217, 330, 190, 318, 269, 260, 203, 44, 28, 473, 228, 177, 863, 704}, - {15, 515, 700, 0, 753, 1, 13, 23, 2, 51, 5, 9, 120, 82, 4, 7, 901, 197, 10, 8, 260, 180, 341, 12, 33, 6, 3, 523, 165, 102, 115, 141}, - {206, 417, 8, 141, 499, 44, 244, 93, 31, 10, 137, 253, 559, 116, 728, 144, 120, 564, 269, 638, 203, 352, 143, 260, 341, 752, 268, 717, 951, 180, 160, 110}, - {530, 254, 228, 1, 96, 21, 406, 39, 827, 31, 669, 840, 613, 829, 137, 679, 166, 98, 23, 51, 960, 438, 131, 93, 48, 224, 219, 317, 310, 36, 876, 190}, - {15, 515, 700, 753, 13, 457, 0, 197, 719, 1, 165, 82, 23, 8, 120, 730, 2, 10, 12, 180, 134, 5, 9, 141, 260, 4, 351, 51, 115, 3, 341, 899}, - {0, 16, 68, 9, 24, 28, 18, 35, 252, 109, 39, 419, 124, 158, 154, 55, 101, 71, 22, 118, 60, 7, 49, 65, 333, 14, 1, 10, 329, 364, 677, 346}, - {1, 15, 13, 23, 515, 51, 120, 0, 700, 180, 2, 165, 5, 753, 141, 197, 21, 33, 202, 102, 260, 4, 9, 12, 7, 326, 137, 450, 115, 6, 82, 110}, - {535, 253, 352, 564, 110, 365, 82, 180, 341, 10, 854, 533, 55, 898, 244, 901, - 873, 141, 752, 143, 642, 559, 498, 317, 36, 951, 115, 964, 638, 282, 661, 197}, - {31, 44, 125, 338, 116, 64, 242, 36, 1, 10, 55, 22, 456, 237, 180, 13, 299, 164, 506, 86, 23, 165, 558, 143, 0, 762, 492, 479, 844, 546, 93, 8}, - {13, 23, 4, 1, 202, 2, 0, 51, 115, 77, 141, 180, 5, 15, 217, 3, 33, 11, 515, 317, 9, 10, 102, 21, 700, 341, 365, 318, 269, 64, 32, 128}, - {9, 39, 0, 166, 68, 101, 28, 364, 30, 158, 562, 35, 175, 65, 333, 154, 49, 404, 706, 124, 21, 252, 274, 168, 190, 289, 100, 570, 16, 1, 310, 346}, - {15, 515, 700, 753, 341, 13, 0, 23, 1, 33, 141, 4, 260, 82, 77, 51, 351, 180, 9, 5, 115, 137, 10, 217, 11, 120, 102, 40, 349, 269, 202, 854} -#else -#include "Table4.h" -#endif -}; - -const uint8_t g_best_total_orderings3[NUM_UNIQUE_TOTAL_ORDERINGS3][32] = { - {12, 1, 3, 5, 27, 2, 4, 38, 8, 7, 16, 18, 6, 10, 41, 79, 40, 23, 46, 9, 20, 88, 22, 37, 14, 19, 24, 126, 99, 119, 35, 11}, - {7, 64, 116, 14, 94, 30, 8, 42, 1, 108, 47, 55, 137, 10, 134, 95, 96, 115, 69, 32, 63, 29, 90, 113, 11, 148, 16, 103, 19, 9, 34, 25}, - {12, 1, 0, 5, 3, 7, 4, 27, 8, 6, 38, 40, 41, 16, 18, 46, 9, 10, 20, 23, 79, 62, 14, 22, 88, 99, 37, 126, 92, 19, 120, 11}, - {16, 88, 27, 18, 46, 48, 126, 107, 79, 19, 59, 38, 37, 65, 23, 66, 0, 2, 3, 43, 12, 151, 28, 25, 5, 87, 72, 40, 1, 20, 52, 92}, - {79, 48, 88, 16, 27, 65, 18, 38, 46, 19, 37, 4, 72, 33, 126, 41, 52, 0, 12, 92, 5, 1, 2, 107, 3, 77, 23, 91, 43, 51, 22, 74}, - {1, 8, 41, 122, 10, 22, 2, 0, 87, 24, 37, 120, 38, 7, 39, 4, 5, 3, 9, 92, 62, 59, 23, 16, 104, 11, 27, 79, 19, 26, 25, 32}, - {2, 76, 99, 28, 40, 86, 93, 21, 138, 60, 6, 0, 17, 128, 145, 119, 98, 144, 141, 82, 147, 54, 67, 75, 5, 12, 27, 132, 146, 1, 38, 14}, - {47, 7, 64, 90, 1, 118, 116, 85, 57, 14, 30, 94, 50, 45, 137, 134, 8, 42, 69, 139, 55, 68, 58, 108, 95, 29, 10, 115, 0, 32, 2, 11}, - {49, 8, 10, 30, 124, 11, 32, 113, 130, 58, 125, 9, 100, 53, 104, 115, 131, 103, 24, 7, 1, 39, 45, 36, 139, 0, 137, 22, 90, 44, 114, 105}, - {9, 38, 72, 125, 49, 41, 84, 11, 13, 5, 27, 0, 16, 92, 8, 2, 65, 105, 10, 18, 48, 29, 127, 131, 36, 14, 1, 46, 111, 79, 130, 12}, - {130, 8, 10, 100, 104, 131, 49, 32, 53, 39, 30, 36, 113, 24, 11, 22, 124, 44, 83, 58, 7, 103, 1, 4, 9, 125, 5, 0, 91, 33, 115, 74}, - {114, 11, 58, 8, 120, 49, 9, 124, 142, 111, 41, 30, 10, 0, 97, 130, 62, 84, 38, 5, 72, 125, 92, 127, 100, 27, 139, 113, 13, 132, 32, 1}, - {60, 46, 28, 27, 40, 20, 0, 17, 18, 2, 126, 16, 6, 38, 86, 23, 79, 54, 1, 93, 5, 88, 41, 14, 21, 111, 7, 48, 3, 84, 72, 62}, - {72, 92, 38, 65, 84, 48, 41, 79, 27, 16, 29, 111, 88, 5, 18, 46, 1, 0, 152, 14, 37, 19, 77, 42, 132, 7, 22, 13, 119, 56, 12, 2}, - {7, 55, 1, 95, 29, 56, 64, 116, 143, 8, 14, 30, 47, 94, 152, 90, 65, 67, 10, 133, 42, 72, 146, 84, 16, 48, 6, 0, 25, 108, 77, 21}, - {27, 23, 20, 5, 0, 79, 38, 2, 3, 1, 59, 46, 4, 41, 33, 86, 37, 87, 88, 92, 7, 126, 43, 8, 22, 152, 151, 150, 149, 148, 147, 146}, - {12, 0, 1, 2, 7, 6, 3, 5, 28, 4, 8, 14, 60, 40, 17, 19, 21, 86, 126, 93, 10, 18, 9, 29, 48, 99, 65, 25, 84, 119, 72, 41}, - {60, 40, 99, 2, 54, 12, 0, 1, 19, 28, 98, 93, 6, 138, 21, 5, 27, 17, 151, 14, 76, 46, 16, 18, 38, 29, 86, 144, 107, 7, 25, 41}, - {12, 0, 1, 2, 3, 5, 6, 7, 4, 28, 8, 60, 14, 40, 16, 17, 21, 10, 19, 9, 86, 38, 126, 41, 93, 27, 29, 48, 62, 84, 79, 99}, - {0, 1, 2, 10, 5, 8, 3, 25, 4, 29, 32, 34, 63, 7, 77, 26, 16, 48, 65, 56, 14, 22, 129, 103, 72, 24, 18, 152, 140, 53, 96, 42}, - {46, 126, 18, 54, 12, 16, 1, 0, 5, 2, 27, 98, 20, 23, 6, 3, 88, 48, 28, 7, 19, 8, 4, 60, 151, 38, 37, 21, 79, 14, 65, 40}, - {76, 6, 141, 86, 119, 2, 138, 67, 28, 145, 0, 93, 17, 1, 40, 60, 146, 99, 147, 14, 21, 144, 132, 7, 5, 29, 55, 27, 16, 75, 19, 12}, - {71, 5, 51, 39, 22, 80, 0, 43, 10, 122, 8, 62, 41, 24, 104, 87, 35, 37, 2, 91, 33, 120, 36, 38, 1, 131, 9, 100, 130, 66, 3, 4}, - {126, 18, 46, 27, 20, 16, 88, 23, 12, 79, 54, 59, 48, 0, 73, 1, 37, 151, 5, 19, 28, 38, 2, 66, 60, 3, 65, 98, 14, 26, 6, 43}, - {22, 10, 8, 5, 0, 71, 35, 80, 104, 39, 24, 51, 100, 1, 62, 32, 2, 130, 11, 41, 7, 9, 53, 43, 49, 83, 122, 120, 30, 44, 37, 38}, - {1, 34, 14, 129, 53, 63, 42, 26, 121, 148, 7, 44, 96, 10, 0, 24, 100, 32, 64, 116, 140, 22, 5, 19, 29, 103, 135, 108, 8, 61, 39, 83}, - {1, 7, 34, 63, 44, 25, 135, 14, 24, 108, 22, 0, 83, 94, 5, 129, 35, 101, 47, 121, 2, 19, 42, 53, 6, 110, 103, 8, 148, 10, 16, 123}, - {12, 28, 16, 60, 18, 1, 6, 21, 14, 0, 86, 19, 2, 48, 93, 17, 38, 29, 7, 5, 65, 126, 46, 72, 41, 79, 84, 119, 40, 56, 54, 88}, - {0, 2, 12, 27, 5, 46, 38, 40, 41, 79, 88, 99, 3, 23, 1, 62, 20, 4, 22, 37, 92, 35, 18, 8, 16, 24, 10, 60, 7, 120, 98, 54}, - {1, 7, 14, 56, 8, 0, 84, 67, 10, 2, 133, 72, 42, 111, 5, 30, 21, 4, 9, 3, 25, 94, 16, 116, 47, 11, 65, 18, 132, 90, 55, 64}, - {30, 8, 124, 139, 45, 11, 58, 90, 113, 137, 7, 115, 10, 32, 1, 49, 94, 85, 9, 47, 108, 103, 0, 97, 63, 14, 50, 114, 53, 106, 100, 25}, - {65, 38, 48, 27, 16, 79, 72, 18, 88, 19, 46, 77, 84, 92, 37, 41, 0, 29, 1, 14, 12, 111, 2, 5, 31, 36, 87, 74, 105, 40, 28, 51}, - {10, 8, 30, 113, 130, 100, 53, 32, 115, 103, 104, 7, 1, 121, 39, 49, 131, 44, 24, 36, 63, 137, 34, 45, 22, 90, 108, 83, 26, 11, 94, 139}, - {51, 52, 43, 33, 5, 74, 16, 37, 71, 91, 38, 3, 36, 87, 48, 22, 4, 0, 122, 41, 39, 18, 66, 27, 79, 24, 65, 88, 59, 23, 62, 92}, - {1, 7, 63, 53, 108, 121, 94, 44, 103, 100, 14, 10, 129, 47, 32, 26, 24, 25, 148, 42, 135, 22, 0, 61, 83, 8, 39, 104, 5, 64, 115, 34}, - {1, 8, 10, 7, 5, 0, 80, 32, 62, 2, 24, 44, 53, 83, 9, 41, 30, 22, 100, 11, 14, 25, 120, 4, 26, 6, 3, 16, 122, 34, 19, 35}, - {74, 4, 36, 48, 33, 91, 39, 79, 22, 16, 65, 5, 131, 38, 24, 71, 27, 52, 0, 105, 51, 18, 88, 104, 3, 31, 10, 37, 72, 19, 41, 130}, - {59, 43, 38, 79, 23, 27, 92, 51, 0, 16, 46, 5, 18, 88, 41, 37, 66, 3, 87, 20, 48, 2, 122, 4, 22, 12, 1, 126, 19, 65, 33, 24}, - {12, 28, 1, 27, 0, 16, 2, 46, 65, 60, 21, 3, 5, 18, 6, 19, 48, 14, 4, 7, 79, 88, 86, 29, 22, 72, 93, 40, 23, 8, 17, 41}, - {22, 91, 39, 33, 24, 71, 5, 131, 36, 10, 51, 0, 130, 8, 104, 2, 35, 125, 9, 43, 52, 49, 83, 80, 100, 41, 122, 3, 37, 38, 4, 16}, - {12, 0, 1, 2, 5, 3, 4, 8, 7, 27, 18, 38, 10, 6, 16, 46, 9, 20, 41, 23, 126, 79, 22, 14, 19, 99, 88, 54, 37, 48, 62, 35}, - {12, 27, 1, 2, 3, 0, 46, 4, 38, 16, 8, 28, 7, 79, 18, 5, 84, 6, 88, 10, 14, 21, 23, 20, 40, 22, 60, 19, 9, 29, 72, 65}, - {1, 14, 7, 55, 95, 29, 8, 94, 30, 56, 10, 108, 77, 116, 152, 64, 32, 48, 63, 42, 143, 148, 16, 25, 137, 65, 11, 0, 115, 9, 19, 72}, - {37, 79, 66, 38, 16, 52, 48, 59, 43, 27, 87, 33, 41, 4, 23, 51, 3, 5, 88, 18, 92, 46, 73, 122, 22, 71, 20, 0, 65, 19, 2, 120}, - {24, 32, 83, 22, 53, 1, 8, 10, 7, 30, 35, 5, 103, 0, 100, 101, 121, 113, 34, 123, 63, 2, 44, 25, 71, 115, 80, 14, 26, 108, 51, 39}, - {97, 45, 111, 58, 85, 139, 0, 90, 47, 7, 120, 106, 142, 30, 50, 132, 41, 62, 84, 1, 119, 114, 14, 56, 117, 8, 38, 29, 2, 64, 116, 5}, - {12, 28, 16, 18, 1, 60, 6, 14, 2, 21, 0, 86, 126, 19, 48, 93, 7, 27, 17, 29, 5, 65, 54, 38, 72, 79, 84, 88, 119, 145, 8, 111}, - {118, 47, 64, 116, 57, 85, 7, 14, 50, 1, 42, 0, 45, 68, 86, 69, 2, 111, 134, 28, 90, 55, 16, 29, 56, 48, 84, 144, 60, 30, 112, 41}, - {12, 1, 2, 0, 7, 6, 28, 5, 3, 4, 8, 14, 60, 21, 18, 40, 17, 86, 10, 9, 16, 29, 19, 93, 126, 79, 38, 84, 72, 27, 111, 119}, - {11, 8, 49, 130, 10, 125, 9, 124, 100, 114, 131, 30, 58, 104, 32, 39, 24, 113, 36, 105, 0, 41, 22, 120, 5, 53, 111, 38, 142, 44, 83, 35}, - {50, 70, 47, 118, 85, 57, 106, 0, 45, 7, 64, 90, 81, 14, 2, 134, 28, 62, 86, 55, 69, 1, 78, 119, 68, 56, 18, 67, 16, 60, 29, 21}, - {43, 37, 33, 87, 51, 41, 66, 5, 122, 38, 22, 59, 92, 0, 23, 91, 27, 16, 71, 79, 18, 52, 120, 4, 3, 24, 46, 20, 73, 39, 62, 36}, - {79, 48, 4, 16, 27, 88, 43, 33, 18, 38, 65, 37, 46, 3, 19, 51, 52, 22, 66, 87, 74, 5, 41, 91, 23, 59, 0, 71, 122, 72, 20, 92}, - {32, 100, 10, 8, 30, 104, 24, 44, 39, 113, 83, 103, 1, 7, 22, 53, 115, 63, 135, 121, 26, 35, 34, 5, 0, 108, 137, 90, 91, 45, 2, 130}, - {0, 1, 2, 5, 16, 12, 6, 7, 14, 3, 19, 18, 29, 20, 4, 21, 40, 8, 17, 35, 23, 48, 126, 22, 25, 56, 26, 10, 98, 27, 38, 65}, - {143, 67, 56, 146, 1, 7, 133, 55, 64, 141, 134, 69, 6, 47, 14, 29, 84, 21, 111, 147, 57, 16, 95, 72, 118, 132, 50, 0, 2, 18, 119, 42}, - {1, 7, 67, 14, 133, 111, 8, 84, 0, 21, 2, 47, 64, 132, 55, 10, 95, 147, 119, 42, 16, 5, 72, 56, 4, 3, 6, 29, 9, 25, 18, 30}, - {68, 57, 69, 112, 144, 86, 102, 2, 134, 55, 0, 70, 118, 64, 75, 47, 14, 28, 93, 143, 67, 7, 50, 149, 1, 21, 29, 56, 119, 95, 60, 78}, - {58, 97, 114, 30, 124, 45, 11, 139, 8, 90, 0, 142, 7, 10, 41, 113, 84, 62, 49, 111, 85, 1, 9, 5, 137, 120, 32, 14, 2, 117, 47, 38}, - {23, 66, 18, 79, 38, 20, 43, 27, 16, 88, 46, 59, 126, 37, 87, 12, 73, 92, 3, 5, 48, 0, 19, 54, 2, 51, 28, 1, 41, 65, 122, 22}, - {0, 12, 2, 27, 5, 40, 46, 38, 1, 41, 3, 79, 88, 23, 99, 4, 20, 62, 22, 54, 92, 18, 8, 37, 16, 35, 10, 7, 19, 120, 144, 24}, - {1, 14, 25, 26, 0, 7, 44, 34, 129, 42, 24, 5, 135, 22, 19, 148, 6, 96, 83, 2, 29, 16, 63, 35, 101, 64, 140, 136, 116, 110, 3, 10}, - {12, 1, 2, 27, 3, 4, 38, 5, 7, 8, 18, 16, 46, 6, 0, 40, 41, 10, 79, 23, 88, 9, 20, 22, 14, 19, 37, 92, 48, 126, 28, 21}, - {7, 1, 10, 32, 108, 103, 94, 47, 8, 53, 25, 14, 34, 115, 100, 129, 121, 130, 148, 42, 64, 116, 63, 26, 44, 0, 24, 30, 113, 4, 104, 22}, - {47, 134, 7, 14, 55, 69, 64, 95, 1, 29, 85, 118, 56, 116, 45, 57, 102, 143, 50, 90, 42, 30, 16, 94, 0, 8, 67, 75, 133, 2, 18, 48}, - {12, 1, 2, 0, 7, 6, 28, 8, 14, 5, 3, 4, 40, 21, 17, 18, 60, 86, 16, 93, 126, 10, 9, 29, 99, 38, 119, 25, 19, 54, 27, 84}, - {59, 16, 27, 18, 23, 88, 79, 37, 46, 66, 38, 20, 73, 126, 3, 43, 48, 87, 92, 51, 41, 12, 19, 5, 52, 107, 65, 0, 151, 122, 54, 2}, - {1, 21, 147, 7, 119, 14, 76, 132, 55, 0, 86, 145, 2, 6, 69, 67, 16, 143, 111, 138, 17, 28, 29, 60, 18, 93, 8, 19, 40, 56, 84, 5}, - {144, 86, 112, 2, 68, 102, 69, 0, 149, 93, 75, 28, 57, 55, 145, 60, 21, 67, 99, 134, 143, 40, 146, 119, 82, 110, 62, 6, 29, 26, 78, 14}, - {102, 57, 55, 69, 143, 75, 146, 67, 56, 68, 134, 2, 29, 141, 0, 21, 6, 14, 133, 118, 64, 1, 7, 95, 47, 84, 111, 28, 147, 82, 72, 119}, - {0, 70, 57, 119, 50, 145, 2, 86, 28, 118, 69, 78, 149, 47, 60, 68, 67, 55, 93, 81, 134, 21, 14, 62, 64, 7, 5, 1, 132, 85, 41, 16}, - {51, 5, 43, 71, 122, 87, 41, 37, 91, 39, 0, 22, 33, 36, 38, 24, 66, 120, 62, 2, 80, 16, 92, 10, 59, 4, 27, 23, 35, 79, 8, 3}, - {12, 1, 2, 0, 7, 6, 28, 5, 8, 14, 3, 21, 40, 4, 60, 17, 86, 18, 16, 93, 10, 9, 126, 119, 99, 29, 19, 41, 38, 27, 25, 92}, - {27, 18, 46, 126, 23, 16, 88, 79, 20, 151, 59, 73, 48, 38, 0, 54, 12, 2, 37, 1, 19, 5, 28, 60, 66, 41, 3, 109, 86, 65, 40, 6}, - {48, 79, 4, 33, 16, 74, 65, 38, 88, 27, 91, 52, 18, 36, 22, 19, 46, 0, 37, 3, 51, 5, 71, 39, 72, 43, 24, 41, 92, 87, 2, 10}, - {86, 2, 144, 93, 28, 112, 141, 6, 102, 21, 99, 60, 75, 0, 68, 82, 69, 146, 67, 149, 55, 40, 145, 76, 111, 147, 56, 119, 110, 143, 26, 132}, - {6, 138, 2, 99, 86, 17, 40, 93, 28, 21, 145, 141, 0, 60, 119, 147, 128, 76, 67, 54, 1, 12, 5, 27, 144, 14, 38, 98, 146, 41, 29, 19}, - {1, 8, 0, 10, 2, 29, 7, 5, 3, 56, 4, 25, 14, 152, 63, 32, 65, 72, 96, 42, 34, 108, 48, 9, 26, 16, 84, 103, 67, 148, 22, 129}, - {149, 145, 0, 86, 2, 28, 93, 144, 62, 60, 119, 101, 21, 41, 5, 35, 78, 99, 26, 40, 12, 68, 57, 67, 110, 120, 69, 18, 55, 76, 132, 70}, - {12, 28, 16, 1, 48, 19, 6, 60, 2, 14, 18, 21, 0, 27, 46, 65, 86, 29, 5, 7, 72, 93, 40, 3, 17, 84, 56, 88, 126, 4, 38, 8}, - {1, 8, 5, 10, 7, 24, 2, 62, 0, 41, 22, 122, 120, 9, 4, 3, 32, 87, 11, 37, 38, 83, 100, 44, 25, 104, 16, 26, 39, 80, 14, 6}, - {0, 119, 62, 86, 145, 149, 28, 132, 93, 2, 120, 67, 60, 41, 35, 5, 144, 21, 123, 38, 111, 81, 84, 56, 12, 44, 24, 50, 92, 55, 40, 22}, - {2, 93, 99, 28, 40, 144, 60, 0, 86, 150, 76, 21, 149, 98, 6, 25, 1, 61, 82, 26, 12, 5, 54, 141, 7, 18, 145, 16, 27, 138, 110, 38}, - {24, 8, 10, 22, 32, 35, 100, 5, 1, 53, 0, 7, 71, 80, 30, 123, 83, 104, 51, 11, 2, 39, 44, 113, 9, 62, 25, 103, 34, 101, 43, 41}, - {12, 1, 2, 0, 7, 6, 28, 5, 40, 60, 8, 16, 3, 18, 14, 4, 86, 21, 17, 93, 41, 10, 9, 99, 27, 119, 38, 19, 126, 22, 48, 145}, - {45, 47, 50, 7, 85, 90, 97, 1, 64, 139, 116, 118, 30, 58, 14, 106, 70, 111, 0, 57, 94, 42, 137, 142, 29, 120, 8, 56, 18, 134, 84, 41}, - {12, 0, 2, 5, 27, 38, 1, 46, 41, 40, 79, 144, 3, 22, 88, 23, 28, 60, 99, 62, 6, 24, 26, 7, 4, 16, 10, 35, 37, 18, 14, 20}, - {37, 38, 59, 92, 0, 5, 23, 51, 79, 41, 27, 22, 2, 3, 87, 16, 46, 4, 1, 43, 20, 33, 18, 88, 24, 71, 8, 10, 48, 19, 126, 122}, - {12, 28, 16, 60, 1, 18, 6, 21, 19, 14, 48, 0, 2, 86, 93, 5, 46, 29, 17, 27, 65, 7, 3, 72, 38, 126, 119, 40, 84, 37, 56, 4}, - {0, 2, 5, 1, 16, 6, 27, 28, 18, 38, 60, 7, 14, 21, 46, 40, 86, 41, 19, 48, 93, 8, 3, 79, 22, 4, 10, 37, 62, 23, 24, 111}, - {85, 7, 90, 30, 47, 139, 45, 50, 94, 58, 137, 1, 8, 64, 14, 116, 118, 115, 113, 11, 124, 108, 0, 10, 97, 57, 32, 70, 42, 106, 29, 114}, - {33, 36, 22, 71, 51, 5, 91, 39, 0, 52, 43, 24, 131, 74, 16, 37, 38, 122, 41, 3, 87, 48, 4, 104, 35, 80, 10, 2, 105, 62, 27, 18}, - {12, 1, 27, 2, 0, 16, 3, 28, 46, 18, 4, 6, 5, 72, 21, 79, 38, 7, 14, 60, 88, 8, 65, 19, 48, 29, 23, 40, 22, 20, 86, 126}, - {0, 12, 2, 27, 5, 38, 46, 41, 1, 40, 79, 3, 88, 23, 22, 99, 20, 37, 62, 4, 18, 6, 16, 35, 60, 28, 24, 7, 92, 8, 14, 10}, - {7, 47, 1, 30, 137, 8, 116, 94, 90, 64, 14, 115, 108, 118, 57, 10, 148, 113, 42, 85, 32, 11, 63, 50, 103, 45, 124, 134, 55, 9, 69, 34}, - {55, 7, 1, 29, 56, 143, 64, 47, 67, 133, 14, 146, 95, 72, 84, 8, 116, 111, 6, 134, 141, 21, 65, 0, 69, 30, 16, 45, 85, 42, 50, 10}, - {14, 1, 42, 8, 10, 29, 108, 63, 55, 148, 95, 32, 7, 19, 25, 115, 103, 34, 56, 129, 77, 0, 16, 152, 94, 30, 113, 26, 2, 5, 48, 4}, - {111, 120, 142, 97, 58, 0, 41, 45, 62, 132, 114, 84, 139, 30, 5, 8, 38, 2, 7, 85, 119, 90, 117, 1, 124, 11, 56, 47, 28, 27, 35, 72}, - {1, 0, 14, 2, 6, 5, 16, 19, 7, 29, 42, 18, 3, 25, 12, 35, 21, 8, 26, 17, 40, 4, 20, 48, 109, 99, 22, 96, 55, 101, 10, 61}, - {12, 0, 1, 5, 3, 2, 4, 7, 27, 8, 38, 6, 40, 18, 16, 10, 20, 46, 9, 41, 23, 22, 79, 14, 62, 19, 37, 126, 88, 11, 92, 48}, - {10, 8, 104, 39, 24, 32, 22, 83, 44, 100, 30, 130, 53, 91, 113, 5, 11, 1, 35, 33, 7, 49, 0, 2, 103, 71, 36, 124, 9, 80, 131, 34}, - {1, 7, 0, 14, 8, 34, 5, 25, 35, 26, 6, 63, 10, 123, 2, 16, 103, 19, 44, 32, 135, 121, 108, 80, 62, 30, 115, 94, 149, 144, 53, 18}, - {75, 68, 146, 141, 102, 67, 2, 21, 6, 57, 69, 143, 0, 55, 82, 86, 28, 144, 147, 29, 93, 112, 56, 119, 133, 14, 76, 60, 84, 134, 111, 145}, - {10, 32, 115, 7, 8, 53, 1, 108, 30, 113, 94, 137, 100, 63, 90, 34, 130, 103, 121, 47, 44, 25, 104, 39, 24, 26, 85, 14, 49, 36, 22, 131}, - {39, 24, 10, 22, 8, 130, 91, 104, 83, 49, 5, 33, 100, 11, 0, 35, 32, 131, 71, 36, 9, 44, 53, 2, 80, 51, 30, 1, 41, 7, 43, 62}, - {38, 36, 65, 105, 27, 72, 31, 79, 41, 131, 5, 48, 125, 39, 0, 16, 92, 46, 22, 13, 18, 84, 24, 37, 88, 2, 33, 74, 91, 71, 130, 49}, - {0, 106, 62, 50, 45, 119, 85, 81, 132, 28, 2, 86, 41, 47, 38, 60, 35, 117, 5, 29, 7, 30, 145, 90, 55, 70, 14, 111, 18, 67, 93, 56}, - {0, 2, 5, 1, 3, 25, 19, 26, 4, 34, 29, 10, 22, 16, 8, 7, 24, 14, 48, 65, 53, 18, 6, 77, 44, 56, 72, 61, 121, 21, 136, 40}, - {7, 1, 94, 8, 47, 115, 10, 32, 113, 103, 30, 108, 137, 63, 14, 64, 116, 148, 129, 42, 90, 25, 34, 118, 53, 57, 11, 49, 85, 9, 96, 50}, - {14, 0, 1, 26, 19, 5, 42, 2, 25, 24, 29, 22, 6, 44, 61, 16, 7, 96, 136, 3, 140, 34, 35, 55, 135, 18, 48, 77, 83, 4, 8, 10}, - {1, 7, 14, 0, 25, 6, 34, 5, 26, 16, 63, 2, 19, 8, 35, 101, 108, 29, 94, 10, 18, 42, 123, 144, 129, 47, 61, 21, 3, 62, 149, 4}, - {12, 0, 2, 1, 28, 5, 6, 120, 7, 60, 40, 16, 18, 86, 27, 14, 21, 93, 8, 62, 41, 38, 3, 17, 4, 119, 99, 48, 19, 126, 10, 9}, - {86, 144, 93, 2, 28, 149, 0, 60, 99, 112, 110, 145, 40, 21, 102, 26, 75, 62, 69, 1, 12, 101, 119, 25, 76, 67, 7, 68, 55, 5, 6, 14}, - {8, 30, 10, 32, 113, 49, 115, 137, 124, 103, 45, 90, 7, 139, 11, 1, 58, 53, 130, 94, 108, 100, 9, 63, 85, 125, 34, 47, 0, 24, 44, 104}, - {120, 142, 111, 41, 58, 114, 97, 0, 11, 62, 84, 124, 5, 30, 8, 38, 132, 127, 27, 139, 92, 10, 72, 45, 49, 9, 28, 2, 29, 56, 16, 1}, - {8, 113, 30, 137, 7, 32, 10, 90, 94, 115, 1, 103, 108, 63, 47, 85, 49, 53, 11, 45, 34, 50, 14, 25, 9, 124, 100, 130, 139, 121, 42, 26}, - {64, 7, 14, 47, 134, 55, 1, 42, 95, 69, 116, 90, 94, 30, 8, 29, 56, 137, 45, 108, 85, 10, 57, 16, 102, 143, 118, 19, 63, 32, 11, 50}, - {62, 132, 0, 119, 120, 41, 111, 86, 35, 28, 5, 84, 56, 38, 2, 93, 145, 60, 67, 12, 92, 27, 29, 72, 55, 117, 21, 24, 133, 149, 22, 45}, - {57, 68, 69, 118, 134, 64, 50, 47, 55, 14, 7, 2, 102, 144, 0, 112, 70, 86, 85, 1, 95, 29, 116, 143, 42, 75, 16, 56, 28, 45, 21, 48}, - {0, 12, 2, 1, 5, 28, 6, 40, 60, 27, 7, 38, 16, 14, 86, 18, 93, 41, 62, 46, 99, 35, 8, 23, 3, 17, 22, 21, 10, 19, 79, 20}, - {12, 1, 2, 27, 16, 3, 38, 111, 4, 0, 18, 5, 7, 46, 40, 8, 79, 6, 14, 28, 88, 10, 48, 41, 19, 84, 21, 9, 22, 23, 20, 72}, - {53, 103, 32, 7, 1, 100, 22, 63, 71, 44, 10, 115, 108, 24, 92, 104, 26, 30, 122, 94, 8, 39, 83, 34, 137, 135, 90, 91, 121, 5, 87, 47}, - {87, 37, 41, 0, 22, 38, 2, 92, 1, 24, 4, 8, 3, 59, 10, 5, 39, 23, 71, 79, 122, 27, 16, 46, 33, 7, 91, 20, 18, 51, 9, 120}, - {1, 7, 8, 10, 0, 5, 35, 32, 53, 44, 14, 30, 2, 80, 25, 34, 6, 62, 26, 103, 16, 19, 63, 9, 149, 24, 121, 41, 22, 11, 113, 83}, - {11, 58, 8, 30, 124, 49, 10, 113, 9, 114, 139, 45, 97, 32, 7, 137, 90, 1, 0, 130, 115, 125, 100, 24, 5, 94, 53, 41, 14, 13, 35, 38}, - {125, 105, 9, 36, 131, 49, 8, 130, 39, 11, 10, 5, 22, 38, 41, 104, 0, 31, 13, 24, 27, 16, 2, 72, 65, 91, 48, 32, 84, 18, 100, 74}, - {12, 1, 0, 2, 6, 3, 7, 5, 4, 8, 14, 28, 16, 60, 18, 10, 21, 17, 19, 9, 40, 27, 86, 93, 29, 38, 54, 11, 25, 48, 46, 41}, - {84, 41, 38, 72, 92, 29, 111, 5, 65, 120, 79, 0, 27, 56, 48, 14, 132, 16, 119, 22, 86, 88, 46, 28, 62, 12, 1, 2, 93, 18, 24, 127}, - {99, 28, 40, 60, 2, 93, 138, 0, 98, 17, 86, 54, 76, 12, 27, 1, 21, 144, 128, 38, 5, 14, 46, 18, 25, 16, 109, 6, 41, 145, 7, 29}, - {1, 63, 10, 32, 148, 14, 103, 34, 42, 7, 8, 108, 116, 53, 64, 96, 25, 121, 26, 94, 140, 0, 29, 19, 55, 24, 100, 136, 5, 4, 44, 115}, - {131, 100, 130, 49, 10, 8, 36, 104, 39, 0, 48, 41, 11, 38, 4, 24, 27, 22, 16, 44, 79, 5, 33, 2, 53, 9, 125, 74, 91, 120, 32, 83}, - {36, 39, 131, 74, 4, 91, 22, 33, 125, 104, 130, 48, 10, 24, 16, 5, 49, 8, 100, 105, 79, 0, 9, 65, 71, 2, 18, 83, 31, 11, 19, 44}, - {0, 12, 2, 1, 6, 5, 7, 28, 40, 60, 16, 14, 18, 62, 86, 27, 93, 8, 17, 38, 21, 41, 35, 99, 3, 19, 10, 23, 22, 4, 9, 48}, - {1, 7, 67, 14, 21, 147, 111, 55, 132, 119, 0, 8, 2, 76, 64, 16, 47, 84, 6, 18, 86, 95, 145, 10, 42, 29, 133, 5, 56, 134, 17, 72}, - {69, 55, 47, 134, 102, 143, 7, 57, 118, 95, 14, 64, 29, 56, 1, 50, 75, 67, 146, 2, 0, 133, 68, 16, 21, 6, 141, 85, 116, 18, 72, 65}, - {1, 44, 7, 24, 83, 63, 34, 103, 22, 121, 53, 32, 25, 35, 0, 115, 108, 5, 14, 8, 10, 101, 94, 30, 2, 123, 110, 26, 137, 47, 90, 19}, - {14, 1, 25, 42, 34, 0, 26, 96, 19, 29, 140, 5, 53, 10, 2, 121, 3, 24, 44, 22, 55, 77, 129, 7, 63, 16, 8, 4, 6, 61, 100, 48}, - {30, 90, 7, 8, 137, 94, 85, 1, 47, 113, 115, 108, 45, 139, 124, 11, 10, 32, 50, 58, 103, 14, 63, 64, 9, 116, 49, 42, 25, 148, 0, 53}, - {40, 99, 2, 60, 28, 17, 0, 54, 93, 98, 86, 138, 6, 12, 21, 76, 1, 5, 27, 144, 128, 38, 19, 46, 14, 41, 145, 7, 16, 67, 3, 109}, - {45, 58, 30, 139, 90, 7, 85, 137, 97, 8, 124, 47, 1, 11, 106, 114, 50, 94, 0, 113, 10, 115, 14, 32, 9, 64, 108, 41, 49, 29, 62, 116}, - {14, 42, 10, 1, 63, 96, 32, 25, 34, 8, 129, 29, 0, 103, 55, 19, 26, 53, 77, 5, 95, 2, 4, 7, 3, 16, 148, 56, 18, 24, 121, 108}, - {21, 2, 75, 86, 6, 76, 144, 28, 119, 99, 93, 147, 141, 67, 102, 145, 60, 132, 146, 128, 0, 82, 40, 138, 55, 111, 143, 17, 133, 112, 69, 14}, - {111, 120, 41, 62, 84, 132, 0, 5, 38, 119, 56, 92, 72, 142, 27, 28, 29, 35, 58, 80, 2, 86, 65, 79, 12, 14, 1, 24, 145, 16, 21, 48}, - {146, 67, 141, 69, 133, 21, 6, 143, 57, 55, 111, 147, 56, 1, 14, 132, 7, 2, 134, 102, 0, 119, 29, 84, 76, 64, 86, 72, 28, 68, 47, 75}, - {12, 1, 0, 5, 27, 3, 7, 4, 38, 8, 6, 41, 16, 40, 46, 10, 18, 79, 2, 9, 23, 86, 20, 22, 62, 14, 37, 88, 92, 19, 24, 11}, - {0, 12, 2, 1, 27, 5, 38, 28, 60, 6, 40, 7, 16, 46, 18, 14, 41, 99, 93, 62, 3, 79, 86, 23, 149, 8, 22, 35, 88, 17, 19, 10}, - {141, 6, 21, 67, 147, 102, 146, 2, 76, 119, 132, 69, 55, 111, 86, 75, 28, 133, 143, 0, 1, 145, 14, 128, 56, 99, 17, 60, 29, 93, 84, 68}, - {21, 76, 1, 119, 86, 145, 2, 0, 14, 7, 6, 138, 146, 55, 17, 28, 132, 93, 67, 40, 60, 143, 29, 147, 111, 16, 69, 141, 5, 56, 19, 133}, - {1, 8, 108, 14, 7, 116, 64, 42, 10, 63, 94, 32, 115, 103, 113, 96, 30, 34, 55, 47, 95, 148, 29, 140, 129, 25, 134, 53, 69, 26, 19, 11}, - {12, 1, 3, 5, 4, 2, 0, 7, 8, 38, 27, 16, 18, 6, 10, 20, 41, 40, 79, 46, 9, 23, 22, 88, 92, 37, 14, 24, 62, 19, 48, 99}, - {1, 14, 7, 0, 6, 25, 5, 16, 19, 2, 42, 26, 29, 35, 61, 8, 18, 129, 101, 21, 3, 110, 34, 148, 96, 10, 17, 4, 22, 40, 12, 20}, - {0, 2, 5, 1, 3, 19, 22, 26, 16, 24, 29, 7, 14, 6, 4, 25, 18, 44, 8, 48, 12, 61, 20, 21, 10, 35, 65, 56, 23, 40, 17, 107}, - {1, 7, 8, 29, 56, 0, 10, 14, 2, 42, 72, 5, 4, 65, 3, 30, 84, 94, 67, 9, 25, 133, 111, 11, 32, 108, 16, 63, 21, 96, 26, 48}}; -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ \ No newline at end of file diff --git a/src/rgbcx/BC1/Tables.h b/src/rgbcx/BC1/Tables.h deleted file mode 100644 index d128703..0000000 --- a/src/rgbcx/BC1/Tables.h +++ /dev/null @@ -1,77 +0,0 @@ -// rgbcx.h v1.12 -// High-performance scalar BC1-5 encoders. Public Domain or MIT license (you choose - see below), written by Richard Geldreich 2020 . - -#pragma once -#include -#include - -// This table is: 9 * (w * w), 9 * ((1.0f - w) * w), 9 * ((1.0f - w) * (1.0f - w)) -// where w is [0,1/3,2/3,1]. 9 is the perfect multiplier. -static constexpr std::array g_weight_vals4 = {0x000009, 0x010204, 0x040201, 0x090000}; - -// multiplier is 4 for 3-color -static constexpr std::array g_weight_vals3 = {0x000004, 0x040000, 0x010101}; - -const uint32_t MIN_TOTAL_ORDERINGS = 1; -const uint32_t MAX_TOTAL_ORDERINGS3 = 32; - -#if RGBCX_USE_SMALLER_TABLES -const uint32_t MAX_TOTAL_ORDERINGS4 = 32; -#else -const uint32_t MAX_TOTAL_ORDERINGS4 = 128; -#endif - -extern const float g_midpoint5[32]; -extern const float g_midpoint6[64]; - -const uint32_t NUM_UNIQUE_TOTAL_ORDERINGS4 = 969; -extern const uint8_t g_unique_total_orders4[NUM_UNIQUE_TOTAL_ORDERINGS4][4]; - -const uint32_t NUM_UNIQUE_TOTAL_ORDERINGS3 = 153; -extern const uint8_t g_unique_total_orders3[NUM_UNIQUE_TOTAL_ORDERINGS3][3]; - -extern const uint16_t g_best_total_orderings4[NUM_UNIQUE_TOTAL_ORDERINGS4][MAX_TOTAL_ORDERINGS4]; - -extern const uint8_t g_best_total_orderings3[NUM_UNIQUE_TOTAL_ORDERINGS3][32]; - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ \ No newline at end of file diff --git a/src/rgbcx/rgbcx.cpp b/src/rgbcx/rgbcx.cpp deleted file mode 100644 index 7d4e1b5..0000000 --- a/src/rgbcx/rgbcx.cpp +++ /dev/null @@ -1,2512 +0,0 @@ -// rgbcx.h v1.12 -// High-performance scalar BC1-5 encoders. Public Domain or MIT license (you choose - see below), written by Richard Geldreich 2020 . - -#pragma GCC diagnostic ignored "-Weverything" -#include "rgbcx.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "BC1/BC1Block.h" -#include "BC1/Tables.h" -#include "Color.h" -#include "util.h" - -namespace rgbcx { - -static const uint32_t TOTAL_ORDER_4_0_16 = 15; -static const uint32_t TOTAL_ORDER_4_1_16 = 700; -static const uint32_t TOTAL_ORDER_4_2_16 = 753; -static const uint32_t TOTAL_ORDER_4_3_16 = 515; -static uint16_t g_total_ordering4_hash[4096]; -static float g_selector_factors4[NUM_UNIQUE_TOTAL_ORDERINGS4][3]; - -static const uint32_t TOTAL_ORDER_3_0_16 = 12; -static const uint32_t TOTAL_ORDER_3_1_16 = 15; -static const uint32_t TOTAL_ORDER_3_2_16 = 89; -static uint16_t g_total_ordering3_hash[256]; -static float g_selector_factors3[NUM_UNIQUE_TOTAL_ORDERINGS3][3]; - -struct hist4 { - uint8_t m_hist[4]; - - hist4() { memset(m_hist, 0, sizeof(m_hist)); } - - hist4(uint32_t i, uint32_t j, uint32_t k, uint32_t l) { - m_hist[0] = (uint8_t)i; - m_hist[1] = (uint8_t)j; - m_hist[2] = (uint8_t)k; - m_hist[3] = (uint8_t)l; - } - - inline bool operator==(const hist4 &h) const { - if (m_hist[0] != h.m_hist[0]) return false; - if (m_hist[1] != h.m_hist[1]) return false; - if (m_hist[2] != h.m_hist[2]) return false; - if (m_hist[3] != h.m_hist[3]) return false; - return true; - } - - inline bool any_16() const { return (m_hist[0] == 16) || (m_hist[1] == 16) || (m_hist[2] == 16) || (m_hist[3] == 16); } - - inline uint32_t lookup_total_ordering_index() const { - if (m_hist[0] == 16) - return TOTAL_ORDER_4_0_16; - else if (m_hist[1] == 16) - return TOTAL_ORDER_4_1_16; - else if (m_hist[2] == 16) - return TOTAL_ORDER_4_2_16; - else if (m_hist[3] == 16) - return TOTAL_ORDER_4_3_16; - - // Must sum to 16, so m_hist[3] isn't needed. - return g_total_ordering4_hash[m_hist[0] | (m_hist[1] << 4) | (m_hist[2] << 8)]; - } -}; - -struct hist3 { - uint8_t m_hist[3]; - - hist3() { memset(m_hist, 0, sizeof(m_hist)); } - - hist3(uint32_t i, uint32_t j, uint32_t k) { - m_hist[0] = (uint8_t)i; - m_hist[1] = (uint8_t)j; - m_hist[2] = (uint8_t)k; - } - - inline bool operator==(const hist3 &h) const { - if (m_hist[0] != h.m_hist[0]) return false; - if (m_hist[1] != h.m_hist[1]) return false; - if (m_hist[2] != h.m_hist[2]) return false; - return true; - } - - inline bool any_16() const { return (m_hist[0] == 16) || (m_hist[1] == 16) || (m_hist[2] == 16); } - - inline uint32_t lookup_total_ordering_index() const { - if (m_hist[0] == 16) - return TOTAL_ORDER_3_0_16; - else if (m_hist[1] == 16) - return TOTAL_ORDER_3_1_16; - else if (m_hist[2] == 16) - return TOTAL_ORDER_3_2_16; - - // Must sum to 16, so m_hist[2] isn't needed. - return g_total_ordering3_hash[m_hist[0] | (m_hist[1] << 4)]; - } -}; - -struct bc1_match_entry { - uint8_t m_hi; - uint8_t m_lo; - uint8_t m_e; -}; - -static bc1_approx_mode g_bc1_approx_mode; -static bc1_match_entry g_bc1_match5_equals_1[256], g_bc1_match6_equals_1[256]; -static bc1_match_entry g_bc1_match5_half[256], g_bc1_match6_half[256]; - -// v0, v1 = unexpanded DXT1 endpoint values (5/6-bits) -// c0, c1 = expanded DXT1 endpoint values (8-bits) -static inline int interp_5_6_ideal(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - return (c0 * 2 + c1) / 3; -} -static inline int interp_5_6_ideal_round(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - return (c0 * 2 + c1 + 1) / 3; -} -static inline int interp_half_5_6_ideal(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - return (c0 + c1) / 2; -} - -static inline int interp_5_nv(int v0, int v1) { - assert(v0 < 32 && v1 < 32); - return ((2 * v0 + v1) * 22) / 8; -} -static inline int interp_6_nv(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - const int gdiff = c1 - c0; - return (256 * c0 + (gdiff / 4) + 128 + gdiff * 80) / 256; -} - -static inline int interp_half_5_nv(int v0, int v1) { - assert(v0 < 32 && v1 < 32); - return ((v0 + v1) * 33) / 8; -} -static inline int interp_half_6_nv(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - const int gdiff = c1 - c0; - return (256 * c0 + gdiff / 4 + 128 + gdiff * 128) / 256; -} - -static inline int interp_5_6_amd(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - return (c0 * 43 + c1 * 21 + 32) >> 6; -} -static inline int interp_half_5_6_amd(int c0, int c1) { - assert(c0 < 256 && c1 < 256); - return (c0 + c1 + 1) >> 1; -} - -static inline int interp_5(int v0, int v1, int c0, int c1, bc1_approx_mode mode) { - // assert(scale_5_to_8(v0) == c0 && scale5To8(v1) == c1); - switch (mode) { - case bc1_approx_mode::cBC1NVidia: - return interp_5_nv(v0, v1); - case bc1_approx_mode::cBC1AMD: - return interp_5_6_amd(c0, c1); - default: - case bc1_approx_mode::cBC1Ideal: - return interp_5_6_ideal(c0, c1); - case bc1_approx_mode::cBC1IdealRound4: - return interp_5_6_ideal_round(c0, c1); - } -} - -static inline int interp_6(int v0, int v1, int c0, int c1, bc1_approx_mode mode) { - (void)v0; - (void)v1; - // assert(scale_6_to_8(v0) == c0 && scale6To8(v1) == c1); - switch (mode) { - case bc1_approx_mode::cBC1NVidia: - return interp_6_nv(c0, c1); - case bc1_approx_mode::cBC1AMD: - return interp_5_6_amd(c0, c1); - default: - case bc1_approx_mode::cBC1Ideal: - return interp_5_6_ideal(c0, c1); - case bc1_approx_mode::cBC1IdealRound4: - return interp_5_6_ideal_round(c0, c1); - } -} - -static inline unsigned int interp_half_5(unsigned int v0, unsigned int v1, unsigned int c0, unsigned int c1, bc1_approx_mode mode) { - assert(scale5To8(v0) == c0 && scale5To8(v1) == c1); - switch (mode) { - case bc1_approx_mode::cBC1NVidia: - return interp_half_5_nv(v0, v1); - case bc1_approx_mode::cBC1AMD: - return interp_half_5_6_amd(c0, c1); - case bc1_approx_mode::cBC1Ideal: - case bc1_approx_mode::cBC1IdealRound4: - default: - return interp_half_5_6_ideal(c0, c1); - } -} - -static inline unsigned int interp_half_6(unsigned v0, unsigned v1, unsigned c0, bc1_approx_mode mode, unsigned c1) { - (void)v0; - (void)v1; - assert(scale6To8(v0) == c0 && scale6To8(v1) == c1); - switch (mode) { - case bc1_approx_mode::cBC1NVidia: - return interp_half_6_nv(c0, c1); - case bc1_approx_mode::cBC1AMD: - return interp_half_5_6_amd(c0, c1); - case bc1_approx_mode::cBC1Ideal: - case bc1_approx_mode::cBC1IdealRound4: - default: - return interp_half_5_6_ideal(c0, c1); - } -} - -static void prepare_bc1_single_color_table_half(bc1_match_entry *pTable, const uint8_t *pExpand, int size, bc1_approx_mode mode) { - for (int i = 0; i < 256; i++) { - int lowest_e = 256; - for (int lo = 0; lo < size; lo++) { - const int lo_e = pExpand[lo]; - - for (int hi = 0; hi < size; hi++) { - const int hi_e = pExpand[hi]; - - const int v = (size == 32) ? interp_half_5(hi, lo, hi_e, lo_e, mode) : interp_half_6(hi, lo, hi_e, mode, lo_e); - - int e = iabs(v - i); - - // We only need to factor in 3% error in BC1 ideal mode. - if ((mode == bc1_approx_mode::cBC1Ideal) || (mode == bc1_approx_mode::cBC1IdealRound4)) e += (iabs(hi_e - lo_e) * 3) / 100; - - // Favor equal endpoints, for lower error on actual GPU's which approximate the interpolation. - if ((e < lowest_e) || ((e == lowest_e) && (lo == hi))) { - pTable[i].m_hi = static_cast(hi); - pTable[i].m_lo = static_cast(lo); - - assert(e <= UINT8_MAX); - pTable[i].m_e = static_cast(e); - - lowest_e = e; - } - - } // hi - } // lo - } -} - -static void prepare_bc1_single_color_table(bc1_match_entry *pTable, const uint8_t *pExpand, int size, bc1_approx_mode mode) { - for (int i = 0; i < 256; i++) { - int lowest_e = 256; - for (int lo = 0; lo < size; lo++) { - const int lo_e = pExpand[lo]; - - for (int hi = 0; hi < size; hi++) { - const int hi_e = pExpand[hi]; - - const int v = (size == 32) ? interp_5(hi, lo, hi_e, lo_e, mode) : interp_6(hi, lo, hi_e, lo_e, mode); - - int e = iabs(v - i); - - if ((mode == bc1_approx_mode::cBC1Ideal) || (mode == bc1_approx_mode::cBC1IdealRound4)) e += (iabs(hi_e - lo_e) * 3) / 100; - - // Favor equal endpoints, for lower error on actual GPU's which approximate the interpolation. - if ((e < lowest_e) || ((e == lowest_e) && (lo == hi))) { - pTable[i].m_hi = static_cast(hi); - pTable[i].m_lo = static_cast(lo); - - assert(e <= UINT8_MAX); - pTable[i].m_e = static_cast(e); - - lowest_e = e; - } - - } // hi - } // lo - } -} - -// This table is: 9 * (w * w), 9 * ((1.0f - w) * w), 9 * ((1.0f - w) * (1.0f - w)) -// where w is [0,1/3,2/3,1]. 9 is the perfect multiplier. -static const uint32_t g_weight_vals4[4] = {0x000009, 0x010204, 0x040201, 0x090000}; - -// multiplier is 4 for 3-color -static const uint32_t g_weight_vals3[3] = {0x000004, 0x040000, 0x010101}; - -static inline void compute_selector_factors4(const hist4 &h, float &iz00, float &iz10, float &iz11) { - uint32_t weight_accum = 0; - for (uint32_t sel = 0; sel < 4; sel++) weight_accum += g_weight_vals4[sel] * h.m_hist[sel]; - - float z00 = (float)((weight_accum >> 16) & 0xFF); - float z10 = (float)((weight_accum >> 8) & 0xFF); - float z11 = (float)(weight_accum & 0xFF); - float z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (fabs(det) < 1e-8f) - det = 0.0f; - else - det = (3.0f / 255.0f) / det; - - iz00 = z11 * det; - iz10 = -z10 * det; - iz11 = z00 * det; -} - -static inline void compute_selector_factors3(const hist3 &h, float &iz00, float &iz10, float &iz11) { - uint32_t weight_accum = 0; - for (uint32_t sel = 0; sel < 3; sel++) weight_accum += g_weight_vals3[sel] * h.m_hist[sel]; - - float z00 = (float)((weight_accum >> 16) & 0xFF); - float z10 = (float)((weight_accum >> 8) & 0xFF); - float z11 = (float)(weight_accum & 0xFF); - float z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (fabs(det) < 1e-8f) - det = 0.0f; - else - det = (2.0f / 255.0f) / det; - - iz00 = z11 * det; - iz10 = -z10 * det; - iz11 = z00 * det; -} - -static bool g_initialized; - -void init(bc1_approx_mode mode) { - g_bc1_approx_mode = mode; - - uint8_t bc1_expand5[32]; - for (int i = 0; i < 32; i++) bc1_expand5[i] = static_cast((i << 3) | (i >> 2)); - prepare_bc1_single_color_table(g_bc1_match5_equals_1, bc1_expand5, 32, mode); - prepare_bc1_single_color_table_half(g_bc1_match5_half, bc1_expand5, 32, mode); - - uint8_t bc1_expand6[64]; - for (int i = 0; i < 64; i++) bc1_expand6[i] = static_cast((i << 2) | (i >> 4)); - prepare_bc1_single_color_table(g_bc1_match6_equals_1, bc1_expand6, 64, mode); - prepare_bc1_single_color_table_half(g_bc1_match6_half, bc1_expand6, 64, mode); - - for (uint32_t i = 0; i < NUM_UNIQUE_TOTAL_ORDERINGS4; i++) { - hist4 h; - h.m_hist[0] = (uint8_t)g_unique_total_orders4[i][0]; - h.m_hist[1] = (uint8_t)g_unique_total_orders4[i][1]; - h.m_hist[2] = (uint8_t)g_unique_total_orders4[i][2]; - h.m_hist[3] = (uint8_t)g_unique_total_orders4[i][3]; - - if (!h.any_16()) { - const uint32_t index = h.m_hist[0] | (h.m_hist[1] << 4) | (h.m_hist[2] << 8); - assert(index < 4096); - g_total_ordering4_hash[index] = (uint16_t)i; - } - - compute_selector_factors4(h, g_selector_factors4[i][0], g_selector_factors4[i][1], g_selector_factors4[i][2]); - } - - for (uint32_t i = 0; i < NUM_UNIQUE_TOTAL_ORDERINGS3; i++) { - hist3 h; - h.m_hist[0] = (uint8_t)g_unique_total_orders3[i][0]; - h.m_hist[1] = (uint8_t)g_unique_total_orders3[i][1]; - h.m_hist[2] = (uint8_t)g_unique_total_orders3[i][2]; - - if (!h.any_16()) { - const uint32_t index = h.m_hist[0] | (h.m_hist[1] << 4); - assert(index < 256); - g_total_ordering3_hash[index] = (uint16_t)i; - } - - compute_selector_factors3(h, g_selector_factors3[i][0], g_selector_factors3[i][1], g_selector_factors3[i][2]); - } - - g_initialized = true; -} - -void encode_bc1_solid_block(void *pDst, uint32_t fr, uint32_t fg, uint32_t fb, bool allow_3color) { - BC1Block *pDst_block = static_cast(pDst); - - uint32_t mask = 0xAA; - int max16 = -1, min16 = 0; - - if (allow_3color) { - const uint32_t err4 = g_bc1_match5_equals_1[fr].m_e + g_bc1_match6_equals_1[fg].m_e + g_bc1_match5_equals_1[fb].m_e; - const uint32_t err3 = g_bc1_match5_half[fr].m_e + g_bc1_match6_half[fg].m_e + g_bc1_match5_half[fb].m_e; - - if (err3 < err4) { - max16 = (g_bc1_match5_half[fr].m_hi << 11) | (g_bc1_match6_half[fg].m_hi << 5) | g_bc1_match5_half[fb].m_hi; - min16 = (g_bc1_match5_half[fr].m_lo << 11) | (g_bc1_match6_half[fg].m_lo << 5) | g_bc1_match5_half[fb].m_lo; - - if (max16 > min16) std::swap(max16, min16); - } - } - - if (max16 == -1) { - max16 = (g_bc1_match5_equals_1[fr].m_hi << 11) | (g_bc1_match6_equals_1[fg].m_hi << 5) | g_bc1_match5_equals_1[fb].m_hi; - min16 = (g_bc1_match5_equals_1[fr].m_lo << 11) | (g_bc1_match6_equals_1[fg].m_lo << 5) | g_bc1_match5_equals_1[fb].m_lo; - - if (min16 == max16) { - // Always forbid 3 color blocks - // This is to guarantee that BC3 blocks never use punchthrough alpha (3 color) mode, which isn't supported on some (all?) GPU's. - mask = 0; - - // Make l > h - if (min16 > 0) - min16--; - else { - // l = h = 0 - assert(min16 == max16 && max16 == 0); - - max16 = 1; - min16 = 0; - mask = 0x55; - } - - assert(max16 > min16); - } - - if (max16 < min16) { - std::swap(max16, min16); - mask ^= 0x55; - } - } - - pDst_block->SetLowColor(static_cast(max16)); - pDst_block->SetHighColor(static_cast(min16)); - pDst_block->selectors[0] = static_cast(mask); - pDst_block->selectors[1] = static_cast(mask); - pDst_block->selectors[2] = static_cast(mask); - pDst_block->selectors[3] = static_cast(mask); -} - -static const float g_midpoint5[32] = {.015686f, .047059f, .078431f, .111765f, .145098f, .176471f, .207843f, .241176f, .274510f, .305882f, .337255f, - .370588f, .403922f, .435294f, .466667f, .5f, .533333f, .564706f, .596078f, .629412f, .662745f, .694118f, - .725490f, .758824f, .792157f, .823529f, .854902f, .888235f, .921569f, .952941f, .984314f, 1e+37f}; -static const float g_midpoint6[64] = {.007843f, .023529f, .039216f, .054902f, .070588f, .086275f, .101961f, .117647f, .133333f, .149020f, .164706f, - .180392f, .196078f, .211765f, .227451f, .245098f, .262745f, .278431f, .294118f, .309804f, .325490f, .341176f, - .356863f, .372549f, .388235f, .403922f, .419608f, .435294f, .450980f, .466667f, .482353f, .500000f, .517647f, - .533333f, .549020f, .564706f, .580392f, .596078f, .611765f, .627451f, .643137f, .658824f, .674510f, .690196f, - .705882f, .721569f, .737255f, .754902f, .772549f, .788235f, .803922f, .819608f, .835294f, .850980f, .866667f, - .882353f, .898039f, .913725f, .929412f, .945098f, .960784f, .976471f, .992157f, 1e+37f}; - -struct vec3F { - float c[3]; -}; - -static inline void compute_least_squares_endpoints4_rgb(vec3F *pXl, vec3F *pXh, int total_r, int total_g, int total_b, float iz00, float iz10, float iz11, - uint32_t s, const uint32_t r_sum[17], const uint32_t g_sum[17], const uint32_t b_sum[17]) { - const float iz01 = iz10; - - const uint32_t f1 = g_unique_total_orders4[s][0]; - const uint32_t f2 = g_unique_total_orders4[s][0] + g_unique_total_orders4[s][1]; - const uint32_t f3 = g_unique_total_orders4[s][0] + g_unique_total_orders4[s][1] + g_unique_total_orders4[s][2]; - uint32_t uq00_r = (r_sum[f2] - r_sum[f1]) + (r_sum[f3] - r_sum[f2]) * 2 + (r_sum[16] - r_sum[f3]) * 3; - uint32_t uq00_g = (g_sum[f2] - g_sum[f1]) + (g_sum[f3] - g_sum[f2]) * 2 + (g_sum[16] - g_sum[f3]) * 3; - uint32_t uq00_b = (b_sum[f2] - b_sum[f1]) + (b_sum[f3] - b_sum[f2]) * 2 + (b_sum[16] - b_sum[f3]) * 3; - - float q10_r = (float)(total_r * 3 - uq00_r); - float q10_g = (float)(total_g * 3 - uq00_g); - float q10_b = (float)(total_b * 3 - uq00_b); - - pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r; - pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r; - - pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g; - pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g; - - pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b; - pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b; -} - -static inline bool compute_least_squares_endpoints4_rgb(const Color *pColors, const uint8_t *pSelectors, vec3F *pXl, vec3F *pXh, int total_r, int total_g, - int total_b) { - uint32_t uq00_r = 0, uq00_g = 0, uq00_b = 0; - uint32_t weight_accum = 0; - for (uint32_t i = 0; i < 16; i++) { - const uint8_t r = pColors[i][0], g = pColors[i][1], b = pColors[i][2]; - const uint8_t sel = pSelectors[i]; - - weight_accum += g_weight_vals4[sel]; - uq00_r += sel * r; - uq00_g += sel * g; - uq00_b += sel * b; - } - - int q10_r = total_r * 3 - uq00_r; - int q10_g = total_g * 3 - uq00_g; - int q10_b = total_b * 3 - uq00_b; - - float z00 = (float)((weight_accum >> 16) & 0xFF); - float z10 = (float)((weight_accum >> 8) & 0xFF); - float z11 = (float)(weight_accum & 0xFF); - float z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (fabs(det) < 1e-8f) return false; - - det = (3.0f / 255.0f) / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r; - pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r; - - pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g; - pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g; - - pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b; - pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b; - - return true; -} - -static inline void compute_least_squares_endpoints3_rgb(vec3F *pXl, vec3F *pXh, int total_r, int total_g, int total_b, float iz00, float iz10, float iz11, - uint32_t s, const uint32_t r_sum[17], const uint32_t g_sum[17], const uint32_t b_sum[17]) { - const float iz01 = iz10; - - // Compensates for BC1 3-color ordering, which is selector 0, 2, 1 - const uint32_t f1 = g_unique_total_orders3[s][0]; - const uint32_t f2 = g_unique_total_orders3[s][0] + g_unique_total_orders3[s][2]; - uint32_t uq00_r = (r_sum[16] - r_sum[f2]) * 2 + (r_sum[f2] - r_sum[f1]); - uint32_t uq00_g = (g_sum[16] - g_sum[f2]) * 2 + (g_sum[f2] - g_sum[f1]); - uint32_t uq00_b = (b_sum[16] - b_sum[f2]) * 2 + (b_sum[f2] - b_sum[f1]); - - float q10_r = (float)(total_r * 2 - uq00_r); - float q10_g = (float)(total_g * 2 - uq00_g); - float q10_b = (float)(total_b * 2 - uq00_b); - - pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r; - pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r; - - pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g; - pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g; - - pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b; - pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b; -} - -static inline bool compute_least_squares_endpoints3_rgb(bool use_black, const Color *pColors, const uint8_t *pSelectors, vec3F *pXl, vec3F *pXh) { - int uq00_r = 0, uq00_g = 0, uq00_b = 0; - uint32_t weight_accum = 0; - int total_r = 0, total_g = 0, total_b = 0; - for (uint32_t i = 0; i < 16; i++) { - const uint8_t r = pColors[i][0], g = pColors[i][1], b = pColors[i][2]; - if (use_black) { - if ((r | g | b) < 4) continue; - } - - const uint8_t sel = pSelectors[i]; - assert(sel <= 3); - if (sel == 3) continue; - - weight_accum += g_weight_vals3[sel]; - - static const uint8_t s_tran[3] = {0, 2, 1}; - const uint8_t tsel = s_tran[sel]; - uq00_r += tsel * r; - uq00_g += tsel * g; - uq00_b += tsel * b; - - total_r += r; - total_g += g; - total_b += b; - } - - int q10_r = total_r * 2 - uq00_r; - int q10_g = total_g * 2 - uq00_g; - int q10_b = total_b * 2 - uq00_b; - - float z00 = (float)((weight_accum >> 16) & 0xFF); - float z10 = (float)((weight_accum >> 8) & 0xFF); - float z11 = (float)(weight_accum & 0xFF); - float z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (fabs(det) < 1e-8f) return false; - - det = (2.0f / 255.0f) / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - pXl->c[0] = iz00 * (float)uq00_r + iz01 * q10_r; - pXh->c[0] = iz10 * (float)uq00_r + iz11 * q10_r; - - pXl->c[1] = iz00 * (float)uq00_g + iz01 * q10_g; - pXh->c[1] = iz10 * (float)uq00_g + iz11 * q10_g; - - pXl->c[2] = iz00 * (float)uq00_b + iz01 * q10_b; - pXh->c[2] = iz10 * (float)uq00_b + iz11 * q10_b; - - return true; -} - -static inline void bc1_get_block_colors4(uint32_t block_r[4], uint32_t block_g[4], uint32_t block_b[4], uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, - uint32_t hg, uint32_t hb) { - block_r[0] = (lr << 3) | (lr >> 2); - block_g[0] = (lg << 2) | (lg >> 4); - block_b[0] = (lb << 3) | (lb >> 2); - block_r[3] = (hr << 3) | (hr >> 2); - block_g[3] = (hg << 2) | (hg >> 4); - block_b[3] = (hb << 3) | (hb >> 2); - - if (g_bc1_approx_mode == bc1_approx_mode::cBC1Ideal) { - block_r[1] = (block_r[0] * 2 + block_r[3]) / 3; - block_g[1] = (block_g[0] * 2 + block_g[3]) / 3; - block_b[1] = (block_b[0] * 2 + block_b[3]) / 3; - block_r[2] = (block_r[3] * 2 + block_r[0]) / 3; - block_g[2] = (block_g[3] * 2 + block_g[0]) / 3; - block_b[2] = (block_b[3] * 2 + block_b[0]) / 3; - } else if (g_bc1_approx_mode == bc1_approx_mode::cBC1IdealRound4) { - block_r[1] = (block_r[0] * 2 + block_r[3] + 1) / 3; - block_g[1] = (block_g[0] * 2 + block_g[3] + 1) / 3; - block_b[1] = (block_b[0] * 2 + block_b[3] + 1) / 3; - block_r[2] = (block_r[3] * 2 + block_r[0] + 1) / 3; - block_g[2] = (block_g[3] * 2 + block_g[0] + 1) / 3; - block_b[2] = (block_b[3] * 2 + block_b[0] + 1) / 3; - } else if (g_bc1_approx_mode == bc1_approx_mode::cBC1AMD) { - block_r[1] = interp_5_6_amd(block_r[0], block_r[3]); - block_g[1] = interp_5_6_amd(block_g[0], block_g[3]); - block_b[1] = interp_5_6_amd(block_b[0], block_b[3]); - block_r[2] = interp_5_6_amd(block_r[3], block_r[0]); - block_g[2] = interp_5_6_amd(block_g[3], block_g[0]); - block_b[2] = interp_5_6_amd(block_b[3], block_b[0]); - } else { - block_r[1] = interp_5_nv(lr, hr); - block_g[1] = interp_6_nv(block_g[0], block_g[3]); - block_b[1] = interp_5_nv(lb, hb); - block_r[2] = interp_5_nv(hr, lr); - block_g[2] = interp_6_nv(block_g[3], block_g[0]); - block_b[2] = interp_5_nv(hb, lb); - } -} - -static inline void bc1_get_block_colors3(uint32_t block_r[3], uint32_t block_g[3], uint32_t block_b[3], uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, - uint32_t hg, uint32_t hb) { - block_r[0] = (lr << 3) | (lr >> 2); - block_g[0] = (lg << 2) | (lg >> 4); - block_b[0] = (lb << 3) | (lb >> 2); - block_r[1] = (hr << 3) | (hr >> 2); - block_g[1] = (hg << 2) | (hg >> 4); - block_b[1] = (hb << 3) | (hb >> 2); - - if ((g_bc1_approx_mode == bc1_approx_mode::cBC1Ideal) || (g_bc1_approx_mode == bc1_approx_mode::cBC1IdealRound4)) { - block_r[2] = (block_r[0] + block_r[1]) / 2; - block_g[2] = (block_g[0] + block_g[1]) / 2; - block_b[2] = (block_b[0] + block_b[1]) / 2; - } else if (g_bc1_approx_mode == bc1_approx_mode::cBC1AMD) { - block_r[2] = interp_half_5_6_amd(block_r[0], block_r[1]); - block_g[2] = interp_half_5_6_amd(block_g[0], block_g[1]); - block_b[2] = interp_half_5_6_amd(block_b[0], block_b[1]); - } else { - block_r[2] = interp_half_5_nv(lr, hr); - block_g[2] = interp_half_6_nv(block_g[0], block_g[1]); - block_b[2] = interp_half_5_nv(lb, hb); - } -} - - -void bc1_find_sels4_noerr(const Color *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, uint8_t *sels) { - uint32_t block_r[4], block_g[4], block_b[4]; - bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb); - - int ar = block_r[3] - block_r[0], ag = block_g[3] - block_g[0], ab = block_b[3] - block_b[0]; - - int dots[4]; - for (uint32_t i = 0; i < 4; i++) dots[i] = (int)block_r[i] * ar + (int)block_g[i] * ag + (int)block_b[i] * ab; - - int t0 = dots[0] + dots[1], t1 = dots[1] + dots[2], t2 = dots[2] + dots[3]; - - ar *= 2; - ag *= 2; - ab *= 2; - - static const uint8_t s_sels[4] = {3, 2, 1, 0}; - - for (uint32_t i = 0; i < 16; i += 4) { - const int d0 = pSrc_pixels[i + 0].r * ar + pSrc_pixels[i + 0].g * ag + pSrc_pixels[i + 0].b * ab; - const int d1 = pSrc_pixels[i + 1].r * ar + pSrc_pixels[i + 1].g * ag + pSrc_pixels[i + 1].b * ab; - const int d2 = pSrc_pixels[i + 2].r * ar + pSrc_pixels[i + 2].g * ag + pSrc_pixels[i + 2].b * ab; - const int d3 = pSrc_pixels[i + 3].r * ar + pSrc_pixels[i + 3].g * ag + pSrc_pixels[i + 3].b * ab; - - sels[i + 0] = s_sels[(d0 <= t0) + (d0 < t1) + (d0 < t2)]; - sels[i + 1] = s_sels[(d1 <= t0) + (d1 < t1) + (d1 < t2)]; - sels[i + 2] = s_sels[(d2 <= t0) + (d2 < t1) + (d2 < t2)]; - sels[i + 3] = s_sels[(d3 <= t0) + (d3 < t1) + (d3 < t2)]; - } -} - -static inline uint32_t bc1_find_sels4_fasterr(const Color *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, - uint8_t sels[16], uint32_t cur_err) { - uint32_t block_r[4], block_g[4], block_b[4]; - bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb); - - int ar = block_r[3] - block_r[0], ag = block_g[3] - block_g[0], ab = block_b[3] - block_b[0]; - - int dots[4]; - for (uint32_t i = 0; i < 4; i++) dots[i] = (int)block_r[i] * ar + (int)block_g[i] * ag + (int)block_b[i] * ab; - - int t0 = dots[0] + dots[1], t1 = dots[1] + dots[2], t2 = dots[2] + dots[3]; - - ar *= 2; - ag *= 2; - ab *= 2; - - static const uint8_t s_sels[4] = {3, 2, 1, 0}; - - uint32_t total_err = 0; - - for (uint32_t i = 0; i < 16; i += 4) { - const int d0 = pSrc_pixels[i + 0].r * ar + pSrc_pixels[i + 0].g * ag + pSrc_pixels[i + 0].b * ab; - const int d1 = pSrc_pixels[i + 1].r * ar + pSrc_pixels[i + 1].g * ag + pSrc_pixels[i + 1].b * ab; - const int d2 = pSrc_pixels[i + 2].r * ar + pSrc_pixels[i + 2].g * ag + pSrc_pixels[i + 2].b * ab; - const int d3 = pSrc_pixels[i + 3].r * ar + pSrc_pixels[i + 3].g * ag + pSrc_pixels[i + 3].b * ab; - - uint8_t sel0 = s_sels[(d0 <= t0) + (d0 < t1) + (d0 < t2)]; - uint8_t sel1 = s_sels[(d1 <= t0) + (d1 < t1) + (d1 < t2)]; - uint8_t sel2 = s_sels[(d2 <= t0) + (d2 < t1) + (d2 < t2)]; - uint8_t sel3 = s_sels[(d3 <= t0) + (d3 < t1) + (d3 < t2)]; - - sels[i + 0] = sel0; - sels[i + 1] = sel1; - sels[i + 2] = sel2; - sels[i + 3] = sel3; - - total_err += - squarei(pSrc_pixels[i + 0].r - block_r[sel0]) + squarei(pSrc_pixels[i + 0].g - block_g[sel0]) + squarei(pSrc_pixels[i + 0].b - block_b[sel0]); - total_err += - squarei(pSrc_pixels[i + 1].r - block_r[sel1]) + squarei(pSrc_pixels[i + 1].g - block_g[sel1]) + squarei(pSrc_pixels[i + 1].b - block_b[sel1]); - total_err += - squarei(pSrc_pixels[i + 2].r - block_r[sel2]) + squarei(pSrc_pixels[i + 2].g - block_g[sel2]) + squarei(pSrc_pixels[i + 2].b - block_b[sel2]); - total_err += - squarei(pSrc_pixels[i + 3].r - block_r[sel3]) + squarei(pSrc_pixels[i + 3].g - block_g[sel3]) + squarei(pSrc_pixels[i + 3].b - block_b[sel3]); - - if (total_err >= cur_err) break; - } - - return total_err; -} - -static inline uint32_t bc1_find_sels4_check2_err(const Color *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, - uint8_t sels[16], uint32_t cur_err) { - uint32_t block_r[4], block_g[4], block_b[4]; - bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb); - - int dr = block_r[3] - block_r[0], dg = block_g[3] - block_g[0], db = block_b[3] - block_b[0]; - - const float f = 4.0f / (float)(squarei(dr) + squarei(dg) + squarei(db) + .00000125f); - - uint32_t total_err = 0; - - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r; - const int g = pSrc_pixels[i].g; - const int b = pSrc_pixels[i].b; - - int sel = (int)((float)((r - (int)block_r[0]) * dr + (g - (int)block_g[0]) * dg + (b - (int)block_b[0]) * db) * f + .5f); - sel = clampi(sel, 1, 3); - - uint32_t err0 = squarei((int)block_r[sel - 1] - (int)r) + squarei((int)block_g[sel - 1] - (int)g) + squarei((int)block_b[sel - 1] - (int)b); - uint32_t err1 = squarei((int)block_r[sel] - (int)r) + squarei((int)block_g[sel] - (int)g) + squarei((int)block_b[sel] - (int)b); - - int best_sel = sel; - uint32_t best_err = err1; - if (err0 == err1) { - // Prefer non-interpolation - if ((best_sel - 1) == 0) best_sel = 0; - } else if (err0 < best_err) { - best_sel = sel - 1; - best_err = err0; - } - - total_err += best_err; - - if (total_err >= cur_err) break; - - sels[i] = (uint8_t)best_sel; - } - return total_err; -} - -static inline uint32_t bc1_find_sels4_fullerr(const Color *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, - uint8_t sels[16], uint32_t cur_err) { - uint32_t block_r[4], block_g[4], block_b[4]; - bc1_get_block_colors4(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb); - - uint32_t total_err = 0; - - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r; - const int g = pSrc_pixels[i].g; - const int b = pSrc_pixels[i].b; - - uint32_t best_err = squarei((int)block_r[0] - (int)r) + squarei((int)block_g[0] - (int)g) + squarei((int)block_b[0] - (int)b); - uint8_t best_sel = 0; - - for (uint32_t j = 1; (j < 4) && best_err; j++) { - uint32_t err = squarei((int)block_r[j] - (int)r) + squarei((int)block_g[j] - (int)g) + squarei((int)block_b[j] - (int)b); - if ((err < best_err) || ((err == best_err) && (j == 3))) { - best_err = err; - best_sel = (uint8_t)j; - } - } - - total_err += best_err; - - if (total_err >= cur_err) break; - - sels[i] = (uint8_t)best_sel; - } - return total_err; -} - -static inline uint32_t bc1_find_sels4(uint32_t flags, const Color *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, uint32_t hb, - uint8_t sels[16], uint32_t cur_err) { - uint32_t err; - - if (flags & cEncodeBC1UseFasterMSEEval) - err = bc1_find_sels4_fasterr(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels, cur_err); - else if (flags & cEncodeBC1UseFullMSEEval) - err = bc1_find_sels4_fullerr(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels, cur_err); - else - err = bc1_find_sels4_check2_err(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels, cur_err); - - return err; -} - -static inline uint32_t bc1_find_sels3_fullerr(bool use_black, const Color *pSrc_pixels, uint32_t lr, uint32_t lg, uint32_t lb, uint32_t hr, uint32_t hg, - uint32_t hb, uint8_t sels[16], uint32_t cur_err) { - uint32_t block_r[3], block_g[3], block_b[3]; - bc1_get_block_colors3(block_r, block_g, block_b, lr, lg, lb, hr, hg, hb); - - uint32_t total_err = 0; - - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r; - const int g = pSrc_pixels[i].g; - const int b = pSrc_pixels[i].b; - - uint32_t best_err = squarei((int)block_r[0] - (int)r) + squarei((int)block_g[0] - (int)g) + squarei((int)block_b[0] - (int)b); - uint32_t best_sel = 0; - - uint32_t err1 = squarei((int)block_r[1] - (int)r) + squarei((int)block_g[1] - (int)g) + squarei((int)block_b[1] - (int)b); - if (err1 < best_err) { - best_err = err1; - best_sel = 1; - } - - uint32_t err2 = squarei((int)block_r[2] - (int)r) + squarei((int)block_g[2] - (int)g) + squarei((int)block_b[2] - (int)b); - if (err2 < best_err) { - best_err = err2; - best_sel = 2; - } - - if (use_black) { - uint32_t err3 = squarei(r) + squarei(g) + squarei(b); - if (err3 < best_err) { - best_err = err3; - best_sel = 3; - } - } - - total_err += best_err; - if (total_err >= cur_err) return total_err; - - sels[i] = (uint8_t)best_sel; - } - - return total_err; -} - -static inline void precise_round_565(const vec3F &xl, const vec3F &xh, int &trial_lr, int &trial_lg, int &trial_lb, int &trial_hr, int &trial_hg, - int &trial_hb) { - trial_lr = (int)(xl.c[0] * 31.0f); - trial_lg = (int)(xl.c[1] * 63.0f); - trial_lb = (int)(xl.c[2] * 31.0f); - - trial_hr = (int)(xh.c[0] * 31.0f); - trial_hg = (int)(xh.c[1] * 63.0f); - trial_hb = (int)(xh.c[2] * 31.0f); - - if ((uint32_t)(trial_lr | trial_lb | trial_hr | trial_hb) > 31U) { - trial_lr = ((uint32_t)trial_lr > 31U) ? (~trial_lr >> 31) & 31 : trial_lr; - trial_hr = ((uint32_t)trial_hr > 31U) ? (~trial_hr >> 31) & 31 : trial_hr; - - trial_lb = ((uint32_t)trial_lb > 31U) ? (~trial_lb >> 31) & 31 : trial_lb; - trial_hb = ((uint32_t)trial_hb > 31U) ? (~trial_hb >> 31) & 31 : trial_hb; - } - - if ((uint32_t)(trial_lg | trial_hg) > 63U) { - trial_lg = ((uint32_t)trial_lg > 63U) ? (~trial_lg >> 31) & 63 : trial_lg; - trial_hg = ((uint32_t)trial_hg > 63U) ? (~trial_hg >> 31) & 63 : trial_hg; - } - - trial_lr = (trial_lr + (xl.c[0] > g_midpoint5[trial_lr])) & 31; - trial_lg = (trial_lg + (xl.c[1] > g_midpoint6[trial_lg])) & 63; - trial_lb = (trial_lb + (xl.c[2] > g_midpoint5[trial_lb])) & 31; - - trial_hr = (trial_hr + (xh.c[0] > g_midpoint5[trial_hr])) & 31; - trial_hg = (trial_hg + (xh.c[1] > g_midpoint6[trial_hg])) & 63; - trial_hb = (trial_hb + (xh.c[2] > g_midpoint5[trial_hb])) & 31; -} - -static inline void precise_round_565_noscale(vec3F xl, vec3F xh, int &trial_lr, int &trial_lg, int &trial_lb, int &trial_hr, int &trial_hg, int &trial_hb) { - xl.c[0] *= 1.0f / 255.0f; - xl.c[1] *= 1.0f / 255.0f; - xl.c[2] *= 1.0f / 255.0f; - - xh.c[0] *= 1.0f / 255.0f; - xh.c[1] *= 1.0f / 255.0f; - xh.c[2] *= 1.0f / 255.0f; - - precise_round_565(xl, xh, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb); -} - -static inline void bc1_encode4(BC1Block *pDst_block, int lr, int lg, int lb, int hr, int hg, int hb, const uint8_t sels[16]) { - uint16_t lc16 = Color::Pack565Unscaled(lr, lg, lb); - uint16_t hc16 = Color::Pack565Unscaled(hr, hg, hb); - - // Always forbid 3 color blocks - if (lc16 == hc16) { - uint8_t mask = 0; - - // Make l > h - if (hc16 > 0) - hc16--; - else { - // lc16 = hc16 = 0 - assert(lc16 == hc16 && hc16 == 0); - - hc16 = 0; - lc16 = 1; - mask = 0x55; // select hc16 - } - - assert(lc16 > hc16); - pDst_block->SetLowColor(static_cast(lc16)); - pDst_block->SetHighColor(static_cast(hc16)); - - pDst_block->selectors[0] = mask; - pDst_block->selectors[1] = mask; - pDst_block->selectors[2] = mask; - pDst_block->selectors[3] = mask; - } else { - uint8_t invert_mask = 0; - if (lc16 < hc16) { - std::swap(lc16, hc16); - invert_mask = 0x55; - } - - assert(lc16 > hc16); - pDst_block->SetLowColor((uint16_t)lc16); - pDst_block->SetHighColor((uint16_t)hc16); - - uint32_t packed_sels = 0; - static const uint8_t s_sel_trans[4] = {0, 2, 3, 1}; - for (uint32_t i = 0; i < 16; i++) packed_sels |= ((uint32_t)s_sel_trans[sels[i]] << (i * 2)); - - // todo: make this less silly to prevent packing and unpacking - pDst_block->selectors[0] = (uint8_t)packed_sels ^ invert_mask; - pDst_block->selectors[1] = (uint8_t)(packed_sels >> 8) ^ invert_mask; - pDst_block->selectors[2] = (uint8_t)(packed_sels >> 16) ^ invert_mask; - pDst_block->selectors[3] = (uint8_t)(packed_sels >> 24) ^ invert_mask; - } -} - -static inline void bc1_encode3(BC1Block *pDst_block, int lr, int lg, int lb, int hr, int hg, int hb, const uint8_t sels[16]) { - uint16_t lc16 = Color::Pack565Unscaled(lr, lg, lb); - uint16_t hc16 = Color::Pack565Unscaled(hr, hg, hb); - - bool invert_flag = false; - if (lc16 > hc16) { - std::swap(lc16, hc16); - invert_flag = true; - } - - assert(lc16 <= hc16); - - pDst_block->SetLowColor((uint16_t)lc16); - pDst_block->SetHighColor((uint16_t)hc16); - - uint32_t packed_sels = 0; - - if (invert_flag) { - static const uint8_t s_sel_trans_inv[4] = {1, 0, 2, 3}; - - for (uint32_t i = 0; i < 16; i++) packed_sels |= ((uint32_t)s_sel_trans_inv[sels[i]] << (i * 2)); - } else { - for (uint32_t i = 0; i < 16; i++) packed_sels |= ((uint32_t)sels[i] << (i * 2)); - } - - // todo: make this less silly to prevent packing and unpacking - pDst_block->selectors[0] = (uint8_t)packed_sels; - pDst_block->selectors[1] = (uint8_t)(packed_sels >> 8); - pDst_block->selectors[2] = (uint8_t)(packed_sels >> 16); - pDst_block->selectors[3] = (uint8_t)(packed_sels >> 24); -} - -struct bc1_encode_results { - int lr, lg, lb; - int hr, hg, hb; - uint8_t sels[16]; - bool m_3color; -}; - -static bool try_3color_block_useblack(const Color *pSrc_pixels, uint32_t flags, uint32_t &cur_err, bc1_encode_results &results) { - int total_r = 0, total_g = 0, total_b = 0; - int max_r = 0, max_g = 0, max_b = 0; - int min_r = 255, min_g = 255, min_b = 255; - int total_pixels = 0; - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; - if ((r | g | b) < 4) continue; - - max_r = std::max(max_r, r); - max_g = std::max(max_g, g); - max_b = std::max(max_b, b); - min_r = std::min(min_r, r); - min_g = std::min(min_g, g); - min_b = std::min(min_b, b); - total_r += r; - total_g += g; - total_b += b; - - total_pixels++; - } - - if (!total_pixels) return false; - - int half_total_pixels = total_pixels >> 1; - int avg_r = (total_r + half_total_pixels) / total_pixels; - int avg_g = (total_g + half_total_pixels) / total_pixels; - int avg_b = (total_b + half_total_pixels) / total_pixels; - - uint32_t low_c = 0, high_c = 0; - - int icov[6] = {0, 0, 0, 0, 0, 0}; - for (uint32_t i = 0; i < 16; i++) { - int r = (int)pSrc_pixels[i].r; - int g = (int)pSrc_pixels[i].g; - int b = (int)pSrc_pixels[i].b; - - if ((r | g | b) < 4) continue; - - r -= avg_r; - g -= avg_g; - b -= avg_b; - - icov[0] += r * r; - icov[1] += r * g; - icov[2] += r * b; - icov[3] += g * g; - icov[4] += g * b; - icov[5] += b * b; - } - - float cov[6]; - for (uint32_t i = 0; i < 6; i++) cov[i] = (float)(icov[i]) * (1.0f / 255.0f); - - float xr = (float)(max_r - min_r); - float xg = (float)(max_g - min_g); - float xb = (float)(max_b - min_b); - - if (icov[2] < 0) xr = -xr; - - if (icov[4] < 0) xg = -xg; - - for (uint32_t power_iter = 0; power_iter < 4; power_iter++) { - float r = xr * cov[0] + xg * cov[1] + xb * cov[2]; - float g = xr * cov[1] + xg * cov[3] + xb * cov[4]; - float b = xr * cov[2] + xg * cov[4] + xb * cov[5]; - xr = r; - xg = g; - xb = b; - } - - float k = maximum(fabsf(xr), fabsf(xg), fabsf(xb)); - int saxis_r = 306, saxis_g = 601, saxis_b = 117; - if (k >= 2) { - float m = 1024.0f / k; - saxis_r = (int)(xr * m); - saxis_g = (int)(xg * m); - saxis_b = (int)(xb * m); - } - - int low_dot = INT_MAX, high_dot = INT_MIN; - for (uint32_t i = 0; i < 16; i++) { - int r = (int)pSrc_pixels[i].r, g = (int)pSrc_pixels[i].g, b = (int)pSrc_pixels[i].b; - - if ((r | g | b) < 4) continue; - - int dot = r * saxis_r + g * saxis_g + b * saxis_b; - if (dot < low_dot) { - low_dot = dot; - low_c = i; - } - if (dot > high_dot) { - high_dot = dot; - high_c = i; - } - } - - int lr = scale8To5(pSrc_pixels[low_c].r); - int lg = scale8To6(pSrc_pixels[low_c].g); - int lb = scale8To5(pSrc_pixels[low_c].b); - - int hr = scale8To5(pSrc_pixels[high_c].r); - int hg = scale8To6(pSrc_pixels[high_c].g); - int hb = scale8To5(pSrc_pixels[high_c].b); - - uint8_t trial_sels[16]; - uint32_t trial_err = bc1_find_sels3_fullerr(true, pSrc_pixels, lr, lg, lb, hr, hg, hb, trial_sels, UINT32_MAX); - - if (trial_err) { - const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1; - for (uint32_t trials = 0; trials < total_ls_passes; trials++) { - vec3F xl, xh; - int lr2, lg2, lb2, hr2, hg2, hb2; - if (!compute_least_squares_endpoints3_rgb(true, pSrc_pixels, trial_sels, &xl, &xh)) { - lr2 = g_bc1_match5_half[avg_r].m_hi; - lg2 = g_bc1_match6_half[avg_g].m_hi; - lb2 = g_bc1_match5_half[avg_b].m_hi; - - hr2 = g_bc1_match5_half[avg_r].m_lo; - hg2 = g_bc1_match6_half[avg_g].m_lo; - hb2 = g_bc1_match5_half[avg_b].m_lo; - } else { - precise_round_565(xl, xh, hr2, hg2, hb2, lr2, lg2, lb2); - } - - if ((lr == lr2) && (lg == lg2) && (lb == lb2) && (hr == hr2) && (hg == hg2) && (hb == hb2)) break; - - uint8_t trial_sels2[16]; - uint32_t trial_err2 = bc1_find_sels3_fullerr(true, pSrc_pixels, lr2, lg2, lb2, hr2, hg2, hb2, trial_sels2, trial_err); - - if (trial_err2 < trial_err) { - trial_err = trial_err2; - lr = lr2; - lg = lg2; - lb = lb2; - hr = hr2; - hg = hg2; - hb = hb2; - memcpy(trial_sels, trial_sels2, sizeof(trial_sels)); - } else - break; - } - } - - if (trial_err < cur_err) { - results.m_3color = true; - results.lr = lr; - results.lg = lg; - results.lb = lb; - results.hr = hr; - results.hg = hg; - results.hb = hb; - memcpy(results.sels, trial_sels, 16); - - cur_err = trial_err; - - return true; - } - - return false; -} - -static bool try_3color_block(const Color *pSrc_pixels, uint32_t flags, uint32_t &cur_err, int avg_r, int avg_g, int avg_b, int lr, int lg, int lb, int hr, - int hg, int hb, int total_r, int total_g, int total_b, uint32_t total_orderings_to_try, bc1_encode_results &results) { - uint8_t trial_sels[16]; - uint32_t trial_err = bc1_find_sels3_fullerr(false, pSrc_pixels, lr, lg, lb, hr, hg, hb, trial_sels, UINT32_MAX); - - if (trial_err) { - const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1; - for (uint32_t trials = 0; trials < total_ls_passes; trials++) { - vec3F xl, xh; - int lr2, lg2, lb2, hr2, hg2, hb2; - if (!compute_least_squares_endpoints3_rgb(false, pSrc_pixels, trial_sels, &xl, &xh)) { - lr2 = g_bc1_match5_half[avg_r].m_hi; - lg2 = g_bc1_match6_half[avg_g].m_hi; - lb2 = g_bc1_match5_half[avg_b].m_hi; - - hr2 = g_bc1_match5_half[avg_r].m_lo; - hg2 = g_bc1_match6_half[avg_g].m_lo; - hb2 = g_bc1_match5_half[avg_b].m_lo; - } else { - precise_round_565(xl, xh, hr2, hg2, hb2, lr2, lg2, lb2); - } - - if ((lr == lr2) && (lg == lg2) && (lb == lb2) && (hr == hr2) && (hg == hg2) && (hb == hb2)) break; - - uint8_t trial_sels2[16]; - uint32_t trial_err2 = bc1_find_sels3_fullerr(false, pSrc_pixels, lr2, lg2, lb2, hr2, hg2, hb2, trial_sels2, trial_err); - - if (trial_err2 < trial_err) { - trial_err = trial_err2; - lr = lr2; - lg = lg2; - lb = lb2; - hr = hr2; - hg = hg2; - hb = hb2; - memcpy(trial_sels, trial_sels2, sizeof(trial_sels)); - } else - break; - } - } - - if ((trial_err) && (flags & cEncodeBC1UseLikelyTotalOrderings) && (total_orderings_to_try)) { - hist3 h; - for (uint32_t i = 0; i < 16; i++) { - assert(trial_sels[i] < 3); - h.m_hist[trial_sels[i]]++; - } - - const uint32_t orig_total_order_index = h.lookup_total_ordering_index(); - - int r0, g0, b0, r3, g3, b3; - r0 = (lr << 3) | (lr >> 2); - g0 = (lg << 2) | (lg >> 4); - b0 = (lb << 3) | (lb >> 2); - r3 = (hr << 3) | (hr >> 2); - g3 = (hg << 2) | (hg >> 4); - b3 = (hb << 3) | (hb >> 2); - - int ar = r3 - r0, ag = g3 - g0, ab = b3 - b0; - - int dots[16]; - for (uint32_t i = 0; i < 16; i++) { - int r = pSrc_pixels[i].r; - int g = pSrc_pixels[i].g; - int b = pSrc_pixels[i].b; - int d = 0x1000000 + (r * ar + g * ag + b * ab); - assert(d >= 0); - dots[i] = (d << 4) + i; - } - - std::sort(dots, dots + 16); - - uint32_t r_sum[17], g_sum[17], b_sum[17]; - uint32_t r = 0, g = 0, b = 0; - for (uint32_t i = 0; i < 16; i++) { - const uint32_t p = dots[i] & 15; - - r_sum[i] = r; - g_sum[i] = g; - b_sum[i] = b; - - r += pSrc_pixels[p].r; - g += pSrc_pixels[p].g; - b += pSrc_pixels[p].b; - } - - r_sum[16] = total_r; - g_sum[16] = total_g; - b_sum[16] = total_b; - - const uint32_t q_total = (flags & cEncodeBC1Exhaustive) ? NUM_UNIQUE_TOTAL_ORDERINGS3 : std::min(total_orderings_to_try, MAX_TOTAL_ORDERINGS3); - for (uint32_t q = 0; q < q_total; q++) { - const uint32_t s = (flags & cEncodeBC1Exhaustive) ? q : g_best_total_orderings3[orig_total_order_index][q]; - - int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb; - - vec3F xl, xh; - - if ((s == TOTAL_ORDER_3_0_16) || (s == TOTAL_ORDER_3_1_16) || (s == TOTAL_ORDER_3_2_16)) { - trial_lr = g_bc1_match5_half[avg_r].m_hi; - trial_lg = g_bc1_match6_half[avg_g].m_hi; - trial_lb = g_bc1_match5_half[avg_b].m_hi; - - trial_hr = g_bc1_match5_half[avg_r].m_lo; - trial_hg = g_bc1_match6_half[avg_g].m_lo; - trial_hb = g_bc1_match5_half[avg_b].m_lo; - } else { - compute_least_squares_endpoints3_rgb(&xl, &xh, total_r, total_g, total_b, g_selector_factors3[s][0], g_selector_factors3[s][1], - g_selector_factors3[s][2], s, r_sum, g_sum, b_sum); - - precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb); - } - - uint8_t trial_sels2[16]; - uint32_t trial_err2 = - bc1_find_sels3_fullerr(false, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels2, UINT32_MAX); - - if (trial_err2 < trial_err) { - trial_err = trial_err2; - - lr = trial_lr; - lg = trial_lg; - lb = trial_lb; - - hr = trial_hr; - hg = trial_hg; - hb = trial_hb; - - memcpy(trial_sels, trial_sels2, sizeof(trial_sels)); - } - - } // s - } - - if (trial_err < cur_err) { - results.m_3color = true; - results.lr = lr; - results.lg = lg; - results.lb = lb; - results.hr = hr; - results.hg = hg; - results.hb = hb; - memcpy(results.sels, trial_sels, 16); - - cur_err = trial_err; - - return true; - } - - return false; -} - -void encode_bc1(uint32_t level, void *pDst, const uint8_t *pPixels, bool allow_3color, bool allow_transparent_texels_for_black) { - uint32_t flags = 0, total_orderings4 = 1, total_orderings3 = 1; - - static_assert(MAX_TOTAL_ORDERINGS3 >= 32, "MAX_TOTAL_ORDERINGS3 >= 32"); - static_assert(MAX_TOTAL_ORDERINGS4 >= 32, "MAX_TOTAL_ORDERINGS4 >= 32"); - - switch (level) { - case 0: - // Faster/higher quality than stb_dxt default. - flags = cEncodeBC1BoundingBoxInt; - break; - case 1: - // Faster/higher quality than stb_dxt default. a bit higher average quality vs. mode 0. - flags = cEncodeBC1Use2DLS; - break; - case 2: - // On average mode 2 is a little weaker than modes 0/1, but it's stronger on outliers (very tough textures). - // Slightly stronger than stb_dxt. - flags = 0; - break; - case 3: - // Slightly stronger than stb_dxt HIGHQUAL. - flags = cEncodeBC1TwoLeastSquaresPasses; - break; - case 4: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1Use6PowerIters; - break; - default: - case 5: - // stb_dxt HIGHQUAL + permit 3 color (if it's enabled). - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - break; - case 6: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - break; - case 7: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 4; - break; - case 8: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFasterMSEEval | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 8; - break; - case 9: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 11; - total_orderings3 = 3; - break; - case 10: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 20; - total_orderings3 = 8; - break; - case 11: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 28; - total_orderings3 = 16; - break; - case 12: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseLikelyTotalOrderings; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 32; - total_orderings3 = 32; - break; - case 13: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - (20 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 32; - total_orderings3 = 32; - break; - case 14: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - (32 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 32; - total_orderings3 = 32; - break; - case 15: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - (32 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = ((((32 + MAX_TOTAL_ORDERINGS4) / 2) + 32) / 2); - total_orderings3 = 32; - break; - case 16: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = (32 + MAX_TOTAL_ORDERINGS4) / 2; - total_orderings3 = 32; - break; - case 17: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = MAX_TOTAL_ORDERINGS4; - total_orderings3 = 32; - break; - case 18: - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - cEncodeBC1Iterative | (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = MAX_TOTAL_ORDERINGS4; - total_orderings3 = 32; - break; - case 19: - // This hidden mode is *extremely* slow and abuses the encoder. It's just for testing/training. - flags = cEncodeBC1TwoLeastSquaresPasses | cEncodeBC1UseFullMSEEval | cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use6PowerIters | - cEncodeBC1Exhaustive | cEncodeBC1Iterative | (256 << cEncodeBC1EndpointSearchRoundsShift) | cEncodeBC1TryAllInitialEndponts; - flags |= (allow_3color ? cEncodeBC1Use3ColorBlocks : 0) | (allow_transparent_texels_for_black ? cEncodeBC1Use3ColorBlocksForBlackPixels : 0); - total_orderings4 = 32; - total_orderings3 = 32; - break; - } - - encode_bc1(pDst, pPixels, flags, total_orderings4, total_orderings3); -} - -// Finds low and high colors to begin with - -void encode_bc1_pick_initial(const Color *pSrc_pixels, uint32_t flags, bool grayscale_flag, int min_r, int min_g, int min_b, int max_r, int max_g, int max_b, - int avg_r, int avg_g, int avg_b, int total_r, int total_g, int total_b, int &lr, int &lg, int &lb, int &hr, int &hg, int &hb) { - if (grayscale_flag) { - const int fr = pSrc_pixels[0].r; - - // Grayscale blocks are a common enough case to specialize. - if ((max_r - min_r) < 2) { - lr = lb = hr = hb = scale8To5(fr); - lg = hg = scale8To6(fr); - } else { - lr = lb = scale8To5(min_r); - lg = scale8To6(min_r); - - hr = hb = scale8To5(max_r); - hg = scale8To6(max_r); - } - } else if (flags & cEncodeBC1Use2DLS) { - // 2D Least Squares approach from Humus's example, with added inset and optimal rounding. - int big_chan = 0, min_chan_val = min_r, max_chan_val = max_r; - if ((max_g - min_g) > (max_chan_val - min_chan_val)) big_chan = 1, min_chan_val = min_g, max_chan_val = max_g; - - if ((max_b - min_b) > (max_chan_val - min_chan_val)) big_chan = 2, min_chan_val = min_b, max_chan_val = max_b; - - int sum_xy_r = 0, sum_xy_g = 0, sum_xy_b = 0; - vec3F l, h; - if (big_chan == 0) { - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; - sum_xy_r += r * r, sum_xy_g += r * g, sum_xy_b += r * b; - } - - int sum_x = total_r; - int sum_x2 = sum_xy_r; - - float div = (float)(16 * sum_x2 - sum_x * sum_x); - float b_y = 0.0f, b_z = 0.0f; - if (fabs(div) > 1e-8f) { - div = 1.0f / div; - b_y = (16 * sum_xy_g - sum_x * total_g) * div; - b_z = (16 * sum_xy_b - sum_x * total_b) * div; - } - - float a_y = (total_g - b_y * sum_x) / 16.0f; - float a_z = (total_b - b_z * sum_x) / 16.0f; - - l.c[1] = a_y + b_y * min_chan_val; - l.c[2] = a_z + b_z * min_chan_val; - - h.c[1] = a_y + b_y * max_chan_val; - h.c[2] = a_z + b_z * max_chan_val; - - float dg = (h.c[1] - l.c[1]); - float db = (h.c[2] - l.c[2]); - - h.c[1] = l.c[1] + dg * (15.0f / 16.0f); - h.c[2] = l.c[2] + db * (15.0f / 16.0f); - - l.c[1] = l.c[1] + dg * (1.0f / 16.0f); - l.c[2] = l.c[2] + db * (1.0f / 16.0f); - - float d = (float)(max_chan_val - min_chan_val); - float fmin_chan_val = min_chan_val + d * (1.0f / 16.0f); - float fmax_chan_val = min_chan_val + d * (15.0f / 16.0f); - - l.c[0] = fmin_chan_val; - h.c[0] = fmax_chan_val; - } else if (big_chan == 1) { - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; - sum_xy_r += g * r, sum_xy_g += g * g, sum_xy_b += g * b; - } - - int sum_x = total_g; - int sum_x2 = sum_xy_g; - - float div = (float)(16 * sum_x2 - sum_x * sum_x); - float b_x = 0.0f, b_z = 0.0f; - if (fabs(div) > 1e-8f) { - div = 1.0f / div; - b_x = (16 * sum_xy_r - sum_x * total_r) * div; - b_z = (16 * sum_xy_b - sum_x * total_b) * div; - } - - float a_x = (total_r - b_x * sum_x) / 16.0f; - float a_z = (total_b - b_z * sum_x) / 16.0f; - - l.c[0] = a_x + b_x * min_chan_val; - l.c[2] = a_z + b_z * min_chan_val; - - h.c[0] = a_x + b_x * max_chan_val; - h.c[2] = a_z + b_z * max_chan_val; - - float dr = (h.c[0] - l.c[0]); - float db = (h.c[2] - l.c[2]); - - h.c[0] = l.c[0] + dr * (15.0f / 16.0f); - h.c[2] = l.c[2] + db * (15.0f / 16.0f); - - l.c[0] = l.c[0] + dr * (1.0f / 16.0f); - l.c[2] = l.c[2] + db * (1.0f / 16.0f); - - float d = (float)(max_chan_val - min_chan_val); - float fmin_chan_val = min_chan_val + d * (1.0f / 16.0f); - float fmax_chan_val = min_chan_val + d * (15.0f / 16.0f); - - l.c[1] = fmin_chan_val; - h.c[1] = fmax_chan_val; - } else { - for (uint32_t i = 0; i < 16; i++) { - const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; - sum_xy_r += b * r, sum_xy_g += b * g, sum_xy_b += b * b; - } - - int sum_x = total_b; - int sum_x2 = sum_xy_b; - - float div = (float)(16 * sum_x2 - sum_x * sum_x); - float b_x = 0.0f, b_y = 0.0f; - if (fabs(div) > 1e-8f) { - div = 1.0f / div; - b_x = (16 * sum_xy_r - sum_x * total_r) * div; - b_y = (16 * sum_xy_g - sum_x * total_g) * div; - } - - float a_x = (total_r - b_x * sum_x) / 16.0f; - float a_y = (total_g - b_y * sum_x) / 16.0f; - - l.c[0] = a_x + b_x * min_chan_val; - l.c[1] = a_y + b_y * min_chan_val; - - h.c[0] = a_x + b_x * max_chan_val; - h.c[1] = a_y + b_y * max_chan_val; - - float dr = (h.c[0] - l.c[0]); - float dg = (h.c[1] - l.c[1]); - - h.c[0] = l.c[0] + dr * (15.0f / 16.0f); - h.c[1] = l.c[1] + dg * (15.0f / 16.0f); - - l.c[0] = l.c[0] + dr * (1.0f / 16.0f); - l.c[1] = l.c[1] + dg * (1.0f / 16.0f); - - float d = (float)(max_chan_val - min_chan_val); - float fmin_chan_val = min_chan_val + d * (1.0f / 16.0f); - float fmax_chan_val = min_chan_val + d * (15.0f / 16.0f); - - l.c[2] = fmin_chan_val; - h.c[2] = fmax_chan_val; - } - - precise_round_565_noscale(l, h, lr, lg, lb, hr, hg, hb); - } else if (flags & cEncodeBC1BoundingBox) { - // Algorithm from icbc.h compress_dxt1_fast() - vec3F l, h; - l.c[0] = min_r * (1.0f / 255.0f); - l.c[1] = min_g * (1.0f / 255.0f); - l.c[2] = min_b * (1.0f / 255.0f); - - h.c[0] = max_r * (1.0f / 255.0f); - h.c[1] = max_g * (1.0f / 255.0f); - h.c[2] = max_b * (1.0f / 255.0f); - - const float bias = 8.0f / 255.0f; - float inset_r = (h.c[0] - l.c[0] - bias) * (1.0f / 16.0f); - float inset_g = (h.c[1] - l.c[1] - bias) * (1.0f / 16.0f); - float inset_b = (h.c[2] - l.c[2] - bias) * (1.0f / 16.0f); - - l.c[0] = clampf(l.c[0] + inset_r, 0.0f, 1.0f); - l.c[1] = clampf(l.c[1] + inset_g, 0.0f, 1.0f); - l.c[2] = clampf(l.c[2] + inset_b, 0.0f, 1.0f); - - h.c[0] = clampf(h.c[0] - inset_r, 0.0f, 1.0f); - h.c[1] = clampf(h.c[1] - inset_g, 0.0f, 1.0f); - h.c[2] = clampf(h.c[2] - inset_b, 0.0f, 1.0f); - - int icov_xz = 0, icov_yz = 0; - for (uint32_t i = 0; i < 16; i++) { - int r = (int)pSrc_pixels[i].r - avg_r; - int g = (int)pSrc_pixels[i].g - avg_g; - int b = (int)pSrc_pixels[i].b - avg_b; - icov_xz += r * b; - icov_yz += g * b; - } - - if (icov_xz < 0) std::swap(l.c[0], h.c[0]); - - if (icov_yz < 0) std::swap(l.c[1], h.c[1]); - - precise_round_565(l, h, lr, lg, lb, hr, hg, hb); - } else if (flags & cEncodeBC1BoundingBoxInt) { - // Algorithm from icbc.h compress_dxt1_fast(), but converted to integer. - int inset_r = (max_r - min_r - 8) >> 4; - int inset_g = (max_g - min_g - 8) >> 4; - int inset_b = (max_b - min_b - 8) >> 4; - - min_r += inset_r; - min_g += inset_g; - min_b += inset_b; - if ((uint32_t)(min_r | min_g | min_b) > 255U) { - min_r = clampi(min_r, 0, 255); - min_g = clampi(min_g, 0, 255); - min_b = clampi(min_b, 0, 255); - } - - max_r -= inset_r; - max_g -= inset_g; - max_b -= inset_b; - if ((uint32_t)(max_r | max_g | max_b) > 255U) { - max_r = clampi(max_r, 0, 255); - max_g = clampi(max_g, 0, 255); - max_b = clampi(max_b, 0, 255); - } - - int icov_xz = 0, icov_yz = 0; - for (uint32_t i = 0; i < 16; i++) { - int r = (int)pSrc_pixels[i].r - avg_r; - int g = (int)pSrc_pixels[i].g - avg_g; - int b = (int)pSrc_pixels[i].b - avg_b; - icov_xz += r * b; - icov_yz += g * b; - } - - int x0 = min_r; - int y0 = min_g; - int x1 = max_r; - int y1 = max_g; - - // swap r and g min and max to align principal axis - if (icov_xz < 0) std::swap(x0, x1); - - if (icov_yz < 0) std::swap(y0, y1); - - lr = scale8To5(x0); - lg = scale8To6(y0); - lb = scale8To5(min_b); - - hr = scale8To5(x1); - hg = scale8To6(y1); - hb = scale8To5(max_b); - } else { - // Select 2 colors along the principle axis. (There must be a faster/simpler way.) - uint32_t low_c = 0, high_c = 0; - - int icov[6] = {0, 0, 0, 0, 0, 0}; - for (uint32_t i = 0; i < 16; i++) { - int r = (int)pSrc_pixels[i].r - avg_r; - int g = (int)pSrc_pixels[i].g - avg_g; - int b = (int)pSrc_pixels[i].b - avg_b; - icov[0] += r * r; //0, 0, 0 - icov[1] += r * g; //1, 0, 1 - icov[2] += r * b; //2, 0, 2 - icov[3] += g * g; //3, 1, 1 - icov[4] += g * b; //4, 1, 2 - icov[5] += b * b; //5, 2, 2 - } - - int saxis_r = 306, saxis_g = 601, saxis_b = 117; - - float xr = (float)(max_r - min_r); - float xg = (float)(max_g - min_g); - float xb = (float)(max_b - min_b); - - if (icov[2] < 0) xr = -xr; - - if (icov[4] < 0) xg = -xg; - - float cov[6]; - for (uint32_t i = 0; i < 6; i++) cov[i] = (float)(icov[i]) * (1.0f / 255.0f); - - const uint32_t total_power_iters = (flags & cEncodeBC1Use6PowerIters) ? 6 : 4; - for (uint32_t power_iter = 0; power_iter < total_power_iters; power_iter++) { - float r = xr * cov[0] + xg * cov[1] + xb * cov[2]; - float g = xr * cov[1] + xg * cov[3] + xb * cov[4]; - float b = xr * cov[2] + xg * cov[4] + xb * cov[5]; - xr = r; - xg = g; - xb = b; - } - - float k = maximum(fabsf(xr), fabsf(xg), fabsf(xb)); - if (k >= 2) { - float m = 2048.0f / k; - saxis_r = (int)(xr * m); - saxis_g = (int)(xg * m); - saxis_b = (int)(xb * m); - } - - int low_dot = INT_MAX, high_dot = INT_MIN; - - saxis_r = (int)((uint32_t)saxis_r << 4U); - saxis_g = (int)((uint32_t)saxis_g << 4U); - saxis_b = (int)((uint32_t)saxis_b << 4U); - - for (uint32_t i = 0; i < 16; i += 4) { - int dot0 = ((pSrc_pixels[i].r * saxis_r + pSrc_pixels[i].g * saxis_g + pSrc_pixels[i].b * saxis_b) & ~0xF) + i; - int dot1 = ((pSrc_pixels[i + 1].r * saxis_r + pSrc_pixels[i + 1].g * saxis_g + pSrc_pixels[i + 1].b * saxis_b) & ~0xF) + i + 1; - int dot2 = ((pSrc_pixels[i + 2].r * saxis_r + pSrc_pixels[i + 2].g * saxis_g + pSrc_pixels[i + 2].b * saxis_b) & ~0xF) + i + 2; - int dot3 = ((pSrc_pixels[i + 3].r * saxis_r + pSrc_pixels[i + 3].g * saxis_g + pSrc_pixels[i + 3].b * saxis_b) & ~0xF) + i + 3; - - int min_d01 = std::min(dot0, dot1); - int max_d01 = std::max(dot0, dot1); - - int min_d23 = std::min(dot2, dot3); - int max_d23 = std::max(dot2, dot3); - - int min_d = std::min(min_d01, min_d23); - int max_d = std::max(max_d01, max_d23); - - low_dot = std::min(low_dot, min_d); - high_dot = std::max(high_dot, max_d); - } - low_c = low_dot & 15; - high_c = high_dot & 15; - - lr = scale8To5(pSrc_pixels[low_c].r); - lg = scale8To6(pSrc_pixels[low_c].g); - lb = scale8To5(pSrc_pixels[low_c].b); - - hr = scale8To5(pSrc_pixels[high_c].r); - hg = scale8To6(pSrc_pixels[high_c].g); - hb = scale8To5(pSrc_pixels[high_c].b); - } -} - -static const int8_t s_adjacent_voxels[16][4] = { - {1, 0, 0, 3}, // 0 - {0, 1, 0, 4}, // 1 - {0, 0, 1, 5}, // 2 - {-1, 0, 0, 0}, // 3 - {0, -1, 0, 1}, // 4 - {0, 0, -1, 2}, // 5 - {1, 1, 0, 9}, // 6 - {1, 0, 1, 10}, // 7 - {0, 1, 1, 11}, // 8 - {-1, -1, 0, 6}, // 9 - {-1, 0, -1, 7}, // 10 - {0, -1, -1, 8}, // 11 - {-1, 1, 0, 13}, // 12 - {1, -1, 0, 12}, // 13 - {0, -1, 1, 15}, // 14 - {0, 1, -1, 14}, // 15 -}; - -// From icbc's high quality mode. -static inline void encode_bc1_endpoint_search(const Color *pSrc_pixels, bool any_black_pixels, uint32_t flags, bc1_encode_results &results, - uint32_t cur_err) { - int &lr = results.lr, &lg = results.lg, &lb = results.lb, &hr = results.hr, &hg = results.hg, &hb = results.hb; - uint8_t *sels = results.sels; - - int prev_improvement_index = 0, forbidden_direction = -1; - - const int endpoint_search_rounds = (flags & cEncodeBC1EndpointSearchRoundsMask) >> cEncodeBC1EndpointSearchRoundsShift; - for (int i = 0; i < endpoint_search_rounds; i++) { - assert(s_adjacent_voxels[s_adjacent_voxels[i & 15][3]][3] == (i & 15)); - - if (forbidden_direction == (i & 31)) continue; - - const int8_t delta[3] = {s_adjacent_voxels[i & 15][0], s_adjacent_voxels[i & 15][1], s_adjacent_voxels[i & 15][2]}; - - int trial_lr = lr, trial_lg = lg, trial_lb = lb, trial_hr = hr, trial_hg = hg, trial_hb = hb; - - if ((i >> 4) & 1) { - trial_lr = clampi(trial_lr + delta[0], 0, 31); - trial_lg = clampi(trial_lg + delta[1], 0, 63); - trial_lb = clampi(trial_lb + delta[2], 0, 31); - } else { - trial_hr = clampi(trial_hr + delta[0], 0, 31); - trial_hg = clampi(trial_hg + delta[1], 0, 63); - trial_hb = clampi(trial_hb + delta[2], 0, 31); - } - - uint8_t trial_sels[16]; - - uint32_t trial_err; - if (results.m_3color) { - trial_err = bc1_find_sels3_fullerr(((any_black_pixels) && ((flags & cEncodeBC1Use3ColorBlocksForBlackPixels) != 0)), pSrc_pixels, trial_lr, - trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, cur_err); - } else { - trial_err = bc1_find_sels4(flags, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, cur_err); - } - - if (trial_err < cur_err) { - cur_err = trial_err; - - forbidden_direction = s_adjacent_voxels[i & 15][3] | (i & 16); - - lr = trial_lr, lg = trial_lg, lb = trial_lb, hr = trial_hr, hg = trial_hg, hb = trial_hb; - - memcpy(sels, trial_sels, 16); - - prev_improvement_index = i; - } - - if (i - prev_improvement_index > 32) break; - } -} - -void encode_bc1(void *pDst, const uint8_t *pPixels, uint32_t flags, uint32_t total_orderings_to_try, uint32_t total_orderings_to_try3) { - assert(g_initialized); - - const Color *pSrc_pixels = (const Color *)pPixels; - BC1Block *pDst_block = static_cast(pDst); - - int avg_r, avg_g, avg_b, min_r, min_g, min_b, max_r, max_g, max_b; - - const uint32_t fr = pSrc_pixels[0].r, fg = pSrc_pixels[0].g, fb = pSrc_pixels[0].b; - - uint32_t j; - for (j = 15; j >= 1; --j) - if ((pSrc_pixels[j].r != fr) || (pSrc_pixels[j].g != fg) || (pSrc_pixels[j].b != fb)) break; - - if (j == 0) { - encode_bc1_solid_block(pDst, fr, fg, fb, (flags & (cEncodeBC1Use3ColorBlocks | cEncodeBC1Use3ColorBlocksForBlackPixels)) != 0); - return; - } - - int total_r = fr, total_g = fg, total_b = fb; - - max_r = fr, max_g = fg, max_b = fb; - min_r = fr, min_g = fg, min_b = fb; - - uint32_t grayscale_flag = (fr == fg) && (fr == fb); - uint32_t any_black_pixels = (fr | fg | fb) < 4; - - for (uint32_t i = 1; i < 16; i++) { - const int r = pSrc_pixels[i].r, g = pSrc_pixels[i].g, b = pSrc_pixels[i].b; - - grayscale_flag &= ((r == g) && (r == b)); - any_black_pixels |= ((r | g | b) < 4); - - max_r = std::max(max_r, r); - max_g = std::max(max_g, g); - max_b = std::max(max_b, b); - min_r = std::min(min_r, r); - min_g = std::min(min_g, g); - min_b = std::min(min_b, b); - total_r += r; - total_g += g; - total_b += b; - } - - avg_r = (total_r + 8) >> 4, avg_g = (total_g + 8) >> 4, avg_b = (total_b + 8) >> 4; - - bc1_encode_results results; - results.m_3color = false; - - uint8_t *sels = results.sels; - int &lr = results.lr, &lg = results.lg, &lb = results.lb, &hr = results.hr, &hg = results.hg, &hb = results.hb; - int orig_lr = 0, orig_lg = 0, orig_lb = 0, orig_hr = 0, orig_hg = 0, orig_hb = 0; - - lr = 0, lg = 0, lb = 0, hr = 0, hg = 0, hb = 0; - - const bool needs_block_error = - ((flags & (cEncodeBC1UseLikelyTotalOrderings | cEncodeBC1Use3ColorBlocks | cEncodeBC1UseFullMSEEval | cEncodeBC1EndpointSearchRoundsMask)) != 0) || - (any_black_pixels && ((flags & cEncodeBC1Use3ColorBlocksForBlackPixels) != 0)); - - uint32_t cur_err = UINT32_MAX; - - if (!needs_block_error) { - assert((flags & cEncodeBC1TryAllInitialEndponts) == 0); - - encode_bc1_pick_initial(pSrc_pixels, flags, grayscale_flag != 0, min_r, min_g, min_b, max_r, max_g, max_b, avg_r, avg_g, avg_b, total_r, total_g, - total_b, lr, lg, lb, hr, hg, hb); - - orig_lr = lr, orig_lg = lg, orig_lb = lb, orig_hr = hr, orig_hg = hg, orig_hb = hb; - - bc1_find_sels4_noerr(pSrc_pixels, lr, lg, lb, hr, hg, hb, sels); - - const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1; - for (uint32_t ls_pass = 0; ls_pass < total_ls_passes; ls_pass++) { - int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb; - - vec3F xl, xh; - if (!compute_least_squares_endpoints4_rgb(pSrc_pixels, sels, &xl, &xh, total_r, total_g, total_b)) { - // All selectors equal - treat it as a solid block which should always be equal or better. - trial_lr = g_bc1_match5_equals_1[avg_r].m_hi; - trial_lg = g_bc1_match6_equals_1[avg_g].m_hi; - trial_lb = g_bc1_match5_equals_1[avg_b].m_hi; - - trial_hr = g_bc1_match5_equals_1[avg_r].m_lo; - trial_hg = g_bc1_match6_equals_1[avg_g].m_lo; - trial_hb = g_bc1_match5_equals_1[avg_b].m_lo; - - // In high/higher quality mode, let it try again in case the optimal tables have caused the sels to diverge. - } else { - precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb); - } - - if ((lr == trial_lr) && (lg == trial_lg) && (lb == trial_lb) && (hr == trial_hr) && (hg == trial_hg) && (hb == trial_hb)) break; - - bc1_find_sels4_noerr(pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, sels); - - lr = trial_lr; - lg = trial_lg; - lb = trial_lb; - hr = trial_hr; - hg = trial_hg; - hb = trial_hb; - - } // ls_pass - } else { - // calculate block error from naïve approach - const uint32_t total_rounds = (flags & cEncodeBC1TryAllInitialEndponts) ? 2 : 1; - for (uint32_t round = 0; round < total_rounds; round++) { - uint32_t modified_flags = flags; - if (round == 1) { - modified_flags &= ~(cEncodeBC1Use2DLS | cEncodeBC1BoundingBox); - modified_flags |= cEncodeBC1BoundingBox; - } - - int round_lr, round_lg, round_lb, round_hr, round_hg, round_hb; - uint8_t round_sels[16]; - - encode_bc1_pick_initial(pSrc_pixels, modified_flags, grayscale_flag != 0, min_r, min_g, min_b, max_r, max_g, max_b, avg_r, avg_g, avg_b, total_r, - total_g, total_b, round_lr, round_lg, round_lb, round_hr, round_hg, round_hb); - - int orig_round_lr = round_lr, orig_round_lg = round_lg, orig_round_lb = round_lb, orig_round_hr = round_hr, orig_round_hg = round_hg, - orig_round_hb = round_hb; - - uint32_t round_err = bc1_find_sels4(flags, pSrc_pixels, round_lr, round_lg, round_lb, round_hr, round_hg, round_hb, round_sels, UINT32_MAX); - - const uint32_t total_ls_passes = flags & cEncodeBC1TwoLeastSquaresPasses ? 2 : 1; - for (uint32_t ls_pass = 0; ls_pass < total_ls_passes; ls_pass++) { - int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb; - - vec3F xl, xh; - if (!compute_least_squares_endpoints4_rgb(pSrc_pixels, round_sels, &xl, &xh, total_r, total_g, total_b)) { - // All selectors equal - treat it as a solid block which should always be equal or better. - trial_lr = g_bc1_match5_equals_1[avg_r].m_hi; - trial_lg = g_bc1_match6_equals_1[avg_g].m_hi; - trial_lb = g_bc1_match5_equals_1[avg_b].m_hi; - - trial_hr = g_bc1_match5_equals_1[avg_r].m_lo; - trial_hg = g_bc1_match6_equals_1[avg_g].m_lo; - trial_hb = g_bc1_match5_equals_1[avg_b].m_lo; - - // In high/higher quality mode, let it try again in case the optimal tables have caused the sels to diverge. - } else { - precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb); - } - - if ((round_lr == trial_lr) && (round_lg == trial_lg) && (round_lb == trial_lb) && (round_hr == trial_hr) && (round_hg == trial_hg) && - (round_hb == trial_hb)) - break; - - uint8_t trial_sels[16]; - uint32_t trial_err = bc1_find_sels4(flags, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, round_err); - - if (trial_err < round_err) { - round_lr = trial_lr; - round_lg = trial_lg; - round_lb = trial_lb; - - round_hr = trial_hr; - round_hg = trial_hg; - round_hb = trial_hb; - - round_err = trial_err; - memcpy(round_sels, trial_sels, 16); - } else - break; - - } // ls_pass - - if (round_err <= cur_err) { - cur_err = round_err; - - lr = round_lr; - lg = round_lg; - lb = round_lb; - hr = round_hr; - hg = round_hg; - hb = round_hb; - - orig_lr = orig_round_lr; - orig_lg = orig_round_lg; - orig_lb = orig_round_lb; - orig_hr = orig_round_hr; - orig_hg = orig_round_hg; - orig_hb = orig_round_hb; - - memcpy(sels, round_sels, 16); - } - - } // round - } - - if ((cur_err) && (flags & cEncodeBC1UseLikelyTotalOrderings)) { - assert(needs_block_error); - - const uint32_t total_iters = (flags & cEncodeBC1Iterative) ? 2 : 1; - for (uint32_t iter_index = 0; iter_index < total_iters; iter_index++) { - const uint32_t orig_err = cur_err; - - hist4 h; - for (uint32_t i = 0; i < 16; i++) { - assert(sels[i] < 4); - h.m_hist[sels[i]]++; - } - - const uint32_t orig_total_order_index = h.lookup_total_ordering_index(); - - int r0, g0, b0, r3, g3, b3; - r0 = (lr << 3) | (lr >> 2); - g0 = (lg << 2) | (lg >> 4); - b0 = (lb << 3) | (lb >> 2); - r3 = (hr << 3) | (hr >> 2); - g3 = (hg << 2) | (hg >> 4); - b3 = (hb << 3) | (hb >> 2); - - int ar = r3 - r0, ag = g3 - g0, ab = b3 - b0; - - int dots[16]; - for (uint32_t i = 0; i < 16; i++) { - int r = pSrc_pixels[i].r; - int g = pSrc_pixels[i].g; - int b = pSrc_pixels[i].b; - int d = 0x1000000 + (r * ar + g * ag + b * ab); - assert(d >= 0); - dots[i] = (d << 4) + i; - } - - std::sort(dots, dots + 16); - - uint32_t r_sum[17], g_sum[17], b_sum[17]; - uint32_t r = 0, g = 0, b = 0; - for (uint32_t i = 0; i < 16; i++) { - const uint32_t p = dots[i] & 15; - - r_sum[i] = r; - g_sum[i] = g; - b_sum[i] = b; - - r += pSrc_pixels[p].r; - g += pSrc_pixels[p].g; - b += pSrc_pixels[p].b; - } - - r_sum[16] = total_r; - g_sum[16] = total_g; - b_sum[16] = total_b; - - const uint32_t q_total = - (flags & cEncodeBC1Exhaustive) ? NUM_UNIQUE_TOTAL_ORDERINGS4 : clampi(total_orderings_to_try, MIN_TOTAL_ORDERINGS, MAX_TOTAL_ORDERINGS4); - for (uint32_t q = 0; q < q_total; q++) { - const uint32_t s = (flags & cEncodeBC1Exhaustive) ? q : g_best_total_orderings4[orig_total_order_index][q]; - - int trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb; - - vec3F xl, xh; - - if ((s == TOTAL_ORDER_4_0_16) || (s == TOTAL_ORDER_4_1_16) || (s == TOTAL_ORDER_4_2_16) || (s == TOTAL_ORDER_4_3_16)) { - trial_lr = g_bc1_match5_equals_1[avg_r].m_hi; - trial_lg = g_bc1_match6_equals_1[avg_g].m_hi; - trial_lb = g_bc1_match5_equals_1[avg_b].m_hi; - - trial_hr = g_bc1_match5_equals_1[avg_r].m_lo; - trial_hg = g_bc1_match6_equals_1[avg_g].m_lo; - trial_hb = g_bc1_match5_equals_1[avg_b].m_lo; - } else { - compute_least_squares_endpoints4_rgb(&xl, &xh, total_r, total_g, total_b, g_selector_factors4[s][0], g_selector_factors4[s][1], - g_selector_factors4[s][2], s, r_sum, g_sum, b_sum); - - precise_round_565(xl, xh, trial_hr, trial_hg, trial_hb, trial_lr, trial_lg, trial_lb); - } - - uint8_t trial_sels[16]; - - uint32_t trial_err = bc1_find_sels4(flags, pSrc_pixels, trial_lr, trial_lg, trial_lb, trial_hr, trial_hg, trial_hb, trial_sels, cur_err); - - if (trial_err < cur_err) { - cur_err = trial_err; - - lr = trial_lr; - lg = trial_lg; - lb = trial_lb; - - hr = trial_hr; - hg = trial_hg; - hb = trial_hb; - - memcpy(sels, trial_sels, 16); - } - - } // s - - if ((!cur_err) || (cur_err == orig_err)) break; - - } // iter_index - } - - if (((flags & (cEncodeBC1Use3ColorBlocks | cEncodeBC1Use3ColorBlocksForBlackPixels)) != 0) && (cur_err)) { - if (flags & cEncodeBC1Use3ColorBlocks) { - assert(needs_block_error); - try_3color_block(pSrc_pixels, flags, cur_err, avg_r, avg_g, avg_b, orig_lr, orig_lg, orig_lb, orig_hr, orig_hg, orig_hb, total_r, total_g, total_b, - total_orderings_to_try3, results); - } - - if ((any_black_pixels) && ((flags & cEncodeBC1Use3ColorBlocksForBlackPixels) != 0)) { - assert(needs_block_error); - try_3color_block_useblack(pSrc_pixels, flags, cur_err, results); - } - } - - if ((flags & cEncodeBC1EndpointSearchRoundsMask) && (cur_err)) { - assert(needs_block_error); - - encode_bc1_endpoint_search(pSrc_pixels, any_black_pixels != 0, flags, results, cur_err); - } - - if (results.m_3color) - bc1_encode3(pDst_block, results.lr, results.lg, results.lb, results.hr, results.hg, results.hb, results.sels); - else - bc1_encode4(pDst_block, results.lr, results.lg, results.lb, results.hr, results.hg, results.hb, results.sels); -} - -// BC3-5 -void encode_bc4(void *pDst, const uint8_t *pPixels, uint32_t stride) { - assert(g_initialized); - - uint32_t min0_v, max0_v, min1_v, max1_v, min2_v, max2_v, min3_v, max3_v; - - { - min0_v = max0_v = pPixels[0 * stride]; - min1_v = max1_v = pPixels[1 * stride]; - min2_v = max2_v = pPixels[2 * stride]; - min3_v = max3_v = pPixels[3 * stride]; - } - - { - uint32_t v0 = pPixels[4 * stride]; - min0_v = std::min(min0_v, v0); - max0_v = std::max(max0_v, v0); - uint32_t v1 = pPixels[5 * stride]; - min1_v = std::min(min1_v, v1); - max1_v = std::max(max1_v, v1); - uint32_t v2 = pPixels[6 * stride]; - min2_v = std::min(min2_v, v2); - max2_v = std::max(max2_v, v2); - uint32_t v3 = pPixels[7 * stride]; - min3_v = std::min(min3_v, v3); - max3_v = std::max(max3_v, v3); - } - - { - uint32_t v0 = pPixels[8 * stride]; - min0_v = std::min(min0_v, v0); - max0_v = std::max(max0_v, v0); - uint32_t v1 = pPixels[9 * stride]; - min1_v = std::min(min1_v, v1); - max1_v = std::max(max1_v, v1); - uint32_t v2 = pPixels[10 * stride]; - min2_v = std::min(min2_v, v2); - max2_v = std::max(max2_v, v2); - uint32_t v3 = pPixels[11 * stride]; - min3_v = std::min(min3_v, v3); - max3_v = std::max(max3_v, v3); - } - - { - uint32_t v0 = pPixels[12 * stride]; - min0_v = std::min(min0_v, v0); - max0_v = std::max(max0_v, v0); - uint32_t v1 = pPixels[13 * stride]; - min1_v = std::min(min1_v, v1); - max1_v = std::max(max1_v, v1); - uint32_t v2 = pPixels[14 * stride]; - min2_v = std::min(min2_v, v2); - max2_v = std::max(max2_v, v2); - uint32_t v3 = pPixels[15 * stride]; - min3_v = std::min(min3_v, v3); - max3_v = std::max(max3_v, v3); - } - - const uint32_t min_v = minimum(min0_v, min1_v, min2_v, min3_v); - const uint32_t max_v = maximum(max0_v, max1_v, max2_v, max3_v); - - uint8_t *pDst_bytes = static_cast(pDst); - pDst_bytes[0] = (uint8_t)max_v; - pDst_bytes[1] = (uint8_t)min_v; - - if (max_v == min_v) { - memset(pDst_bytes + 2, 0, 6); - return; - } - - const uint32_t delta = max_v - min_v; - - // min_v is now 0. Compute thresholds between values by scaling max_v. It's x14 because we're adding two x7 scale factors. - const int t0 = delta * 13; - const int t1 = delta * 11; - const int t2 = delta * 9; - const int t3 = delta * 7; - const int t4 = delta * 5; - const int t5 = delta * 3; - const int t6 = delta * 1; - - // BC4 floors in its divisions, which we compensate for with the 4 bias. - // This function is optimal for all possible inputs (i.e. it outputs the same results as checking all 8 values and choosing the closest one). - const int bias = 4 - min_v * 14; - - static const uint32_t s_tran0[8] = {1U, 7U, 6U, 5U, 4U, 3U, 2U, 0U}; - static const uint32_t s_tran1[8] = {1U << 3U, 7U << 3U, 6U << 3U, 5U << 3U, 4U << 3U, 3U << 3U, 2U << 3U, 0U << 3U}; - static const uint32_t s_tran2[8] = {1U << 6U, 7U << 6U, 6U << 6U, 5U << 6U, 4U << 6U, 3U << 6U, 2U << 6U, 0U << 6U}; - static const uint32_t s_tran3[8] = {1U << 9U, 7U << 9U, 6U << 9U, 5U << 9U, 4U << 9U, 3U << 9U, 2U << 9U, 0U << 9U}; - - uint64_t a0, a1, a2, a3; - { - const int v0 = pPixels[0 * stride] * 14 + bias; - const int v1 = pPixels[1 * stride] * 14 + bias; - const int v2 = pPixels[2 * stride] * 14 + bias; - const int v3 = pPixels[3 * stride] * 14 + bias; - a0 = s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]; - a1 = s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]; - a2 = s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]; - a3 = s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]; - } - - { - const int v0 = pPixels[4 * stride] * 14 + bias; - const int v1 = pPixels[5 * stride] * 14 + bias; - const int v2 = pPixels[6 * stride] * 14 + bias; - const int v3 = pPixels[7 * stride] * 14 + bias; - a0 |= (uint64_t)(s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)] << 12U); - a1 |= (uint64_t)(s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)] << 12U); - a2 |= (uint64_t)(s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)] << 12U); - a3 |= (uint64_t)(s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)] << 12U); - } - - { - const int v0 = pPixels[8 * stride] * 14 + bias; - const int v1 = pPixels[9 * stride] * 14 + bias; - const int v2 = pPixels[10 * stride] * 14 + bias; - const int v3 = pPixels[11 * stride] * 14 + bias; - a0 |= (((uint64_t)s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]) << 24U); - a1 |= (((uint64_t)s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]) << 24U); - a2 |= (((uint64_t)s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]) << 24U); - a3 |= (((uint64_t)s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]) << 24U); - } - - { - const int v0 = pPixels[12 * stride] * 14 + bias; - const int v1 = pPixels[13 * stride] * 14 + bias; - const int v2 = pPixels[14 * stride] * 14 + bias; - const int v3 = pPixels[15 * stride] * 14 + bias; - a0 |= (((uint64_t)s_tran0[(v0 >= t0) + (v0 >= t1) + (v0 >= t2) + (v0 >= t3) + (v0 >= t4) + (v0 >= t5) + (v0 >= t6)]) << 36U); - a1 |= (((uint64_t)s_tran1[(v1 >= t0) + (v1 >= t1) + (v1 >= t2) + (v1 >= t3) + (v1 >= t4) + (v1 >= t5) + (v1 >= t6)]) << 36U); - a2 |= (((uint64_t)s_tran2[(v2 >= t0) + (v2 >= t1) + (v2 >= t2) + (v2 >= t3) + (v2 >= t4) + (v2 >= t5) + (v2 >= t6)]) << 36U); - a3 |= (((uint64_t)s_tran3[(v3 >= t0) + (v3 >= t1) + (v3 >= t2) + (v3 >= t3) + (v3 >= t4) + (v3 >= t5) + (v3 >= t6)]) << 36U); - } - - const uint64_t f = a0 | a1 | a2 | a3; - - // TODO: make this less silly by using the BC4Block class - pDst_bytes[2] = (uint8_t)f; - pDst_bytes[3] = (uint8_t)(f >> 8U); - pDst_bytes[4] = (uint8_t)(f >> 16U); - pDst_bytes[5] = (uint8_t)(f >> 24U); - pDst_bytes[6] = (uint8_t)(f >> 32U); - pDst_bytes[7] = (uint8_t)(f >> 40U); -} - -void encode_bc3(BC3Block *pDst, const uint8_t *pPixels, uint32_t flags, uint32_t total_orderings_to_try) { - assert(g_initialized); - - // 3-color blocks are not allowed with BC3 (on most GPU's). - flags &= ~(cEncodeBC1Use3ColorBlocksForBlackPixels | cEncodeBC1Use3ColorBlocks); - - encode_bc4(&pDst->alpha_block, pPixels + 3, 4); - encode_bc1(&pDst->color_block, pPixels, flags, total_orderings_to_try); -} - -void encode_bc3(uint32_t level, BC3Block *pDst, const uint8_t *pPixels) { - assert(g_initialized); - - encode_bc4(&pDst->alpha_block, pPixels + 3, 4); - encode_bc1(level, &pDst->color_block, pPixels, false, false); -} - -void encode_bc5(BC5Block *pDst, const uint8_t *pPixels, uint32_t chan0, uint32_t chan1, uint32_t stride) { - assert(g_initialized); - - encode_bc4(&pDst->chan0_block, pPixels + chan0, stride); - encode_bc4(&pDst->chan1_block, pPixels + chan1, stride); -} - -// Returns true if the block uses 3 color punchthrough alpha mode. -bool unpack_bc1(const void *pBlock_bits, void *pPixels, bool set_alpha, bc1_approx_mode mode) { - Color *pDst_pixels = static_cast(pPixels); - - static_assert(sizeof(BC1Block) == 8, "sizeof(BC1Block) == 8"); - static_assert(sizeof(BC4Block) == 8, "sizeof(BC4Block) == 8"); - - const BC1Block *pBlock = static_cast(pBlock_bits); - - const uint32_t l = pBlock->GetLowColor(); - const uint32_t h = pBlock->GetHighColor(); - - Color c[4]; - - const int cr0 = (l >> 11) & 31; - const int cg0 = (l >> 5) & 63; - const int cb0 = l & 31; - const int r0 = (cr0 << 3) | (cr0 >> 2); - const int g0 = (cg0 << 2) | (cg0 >> 4); - const int b0 = (cb0 << 3) | (cb0 >> 2); - - const int cr1 = (h >> 11) & 31; - const int cg1 = (h >> 5) & 63; - const int cb1 = h & 31; - const int r1 = (cr1 << 3) | (cr1 >> 2); - const int g1 = (cg1 << 2) | (cg1 >> 4); - const int b1 = (cb1 << 3) | (cb1 >> 2); - - bool used_punchthrough = false; - - if (l > h) { - c[0].SetRGBA(r0, g0, b0, 255); - c[1].SetRGBA(r1, g1, b1, 255); - switch (mode) { - case bc1_approx_mode::cBC1Ideal: - c[2].SetRGBA((r0 * 2 + r1) / 3, (g0 * 2 + g1) / 3, (b0 * 2 + b1) / 3, 255); - c[3].SetRGBA((r1 * 2 + r0) / 3, (g1 * 2 + g0) / 3, (b1 * 2 + b0) / 3, 255); - break; - case bc1_approx_mode::cBC1IdealRound4: - c[2].SetRGBA((r0 * 2 + r1 + 1) / 3, (g0 * 2 + g1 + 1) / 3, (b0 * 2 + b1 + 1) / 3, 255); - c[3].SetRGBA((r1 * 2 + r0 + 1) / 3, (g1 * 2 + g0 + 1) / 3, (b1 * 2 + b0 + 1) / 3, 255); - break; - case bc1_approx_mode::cBC1NVidia: - c[2].SetRGBA(interp_5_nv(cr0, cr1), interp_6_nv(g0, g1), interp_5_nv(cb0, cb1), 255); - c[3].SetRGBA(interp_5_nv(cr1, cr0), interp_6_nv(g1, g0), interp_5_nv(cb1, cb0), 255); - break; - case bc1_approx_mode::cBC1AMD: - c[2].SetRGBA(interp_5_6_amd(r0, r1), interp_5_6_amd(g0, g1), interp_5_6_amd(b0, b1), 255); - c[3].SetRGBA(interp_5_6_amd(r1, r0), interp_5_6_amd(g1, g0), interp_5_6_amd(b1, b0), 255); - break; - } - } else { - c[0].SetRGBA(r0, g0, b0, 255); - c[1].SetRGBA(r1, g1, b1, 255); - switch (mode) { - case bc1_approx_mode::cBC1Ideal: - case bc1_approx_mode::cBC1IdealRound4: - c[2].SetRGBA((r0 + r1) / 2, (g0 + g1) / 2, (b0 + b1) / 2, 255); - break; - case bc1_approx_mode::cBC1NVidia: - c[2].SetRGBA(interp_half_5_nv(cr0, cr1), interp_half_6_nv(g0, g1), interp_half_5_nv(cb0, cb1), 255); - break; - case bc1_approx_mode::cBC1AMD: - c[2].SetRGBA(interp_half_5_6_amd(r0, r1), interp_half_5_6_amd(g0, g1), interp_half_5_6_amd(b0, b1), 255); - break; - } - - c[3].SetRGBA(0, 0, 0, 0); - used_punchthrough = true; - } - - if (set_alpha) { - for (uint32_t y = 0; y < 4; y++, pDst_pixels += 4) { - pDst_pixels[0] = c[pBlock->GetSelector(0, y)]; - pDst_pixels[1] = c[pBlock->GetSelector(1, y)]; - pDst_pixels[2] = c[pBlock->GetSelector(2, y)]; - pDst_pixels[3] = c[pBlock->GetSelector(3, y)]; - } - } else { - for (uint32_t y = 0; y < 4; y++, pDst_pixels += 4) { - pDst_pixels[0].SetRGBA(c[pBlock->GetSelector(0, y)]); - pDst_pixels[1].SetRGBA(c[pBlock->GetSelector(1, y)]); - pDst_pixels[2].SetRGBA(c[pBlock->GetSelector(2, y)]); - pDst_pixels[3].SetRGBA(c[pBlock->GetSelector(3, y)]); - } - } - - return used_punchthrough; -} - -void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride) { - static_assert(sizeof(BC4Block) == 8, "sizeof(BC4Block) == 8"); - - const BC4Block *pBlock = static_cast(pBlock_bits); - - auto sel_values = BC4Block::GetValues(pBlock->GetLowAlpha(), pBlock->GetHighAlpha()); - - const uint64_t selector_bits = pBlock->GetSelectorBits(); - - for (uint32_t y = 0; y < 4; y++, pPixels += (stride * 4U)) { - pPixels[0] = sel_values[pBlock->GetSelector(0, y, selector_bits)]; - pPixels[stride * 1] = sel_values[pBlock->GetSelector(1, y, selector_bits)]; - pPixels[stride * 2] = sel_values[pBlock->GetSelector(2, y, selector_bits)]; - pPixels[stride * 3] = sel_values[pBlock->GetSelector(3, y, selector_bits)]; - } -} - -// Returns false if the block uses 3-color punchthrough alpha mode, which isn't supported on some GPU's for BC3. -bool unpack_bc3(const void *pBlock_bits, void *pPixels, bc1_approx_mode mode) { - Color *pDst_pixels = static_cast(pPixels); - - bool success = true; - - if (unpack_bc1((const uint8_t *)pBlock_bits + sizeof(BC4Block), pDst_pixels, true, mode)) success = false; - - unpack_bc4(pBlock_bits, &pDst_pixels[0].a, sizeof(Color)); - - return success; -} - -// writes RG -void unpack_bc5(const void *pBlock_bits, void *pPixels, uint32_t chan0, uint32_t chan1, uint32_t stride) { - unpack_bc4(pBlock_bits, (uint8_t *)pPixels + chan0, stride); - unpack_bc4((const uint8_t *)pBlock_bits + sizeof(BC4Block), (uint8_t *)pPixels + chan1, stride); -} - -} // namespace rgbcx - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ \ No newline at end of file diff --git a/src/rgbcx/rgbcx.h b/src/rgbcx/rgbcx.h deleted file mode 100644 index 662f512..0000000 --- a/src/rgbcx/rgbcx.h +++ /dev/null @@ -1,246 +0,0 @@ -// rgbcx.h v1.12 -// High-performance scalar BC1-5 encoders. Public Domain or MIT license (you choose - see below), written by Richard Geldreich 2020 . -// -// Influential references: -// http://sjbrown.co.uk/2006/01/19/dxt-compression-techniques/ -// https://github.com/nothings/stb/blob/master/stb_dxt.h -// https://gist.github.com/castano/c92c7626f288f9e99e158520b14a61cf -// https://github.com/castano/icbc/blob/master/icbc.h -// http://www.humus.name/index.php?page=3D&ID=79 -// -// Instructions: -// -// The library MUST be initialized by calling this function at least once before using any encoder or decoder functions: -// -// void rgbcx::init(bc1_approx_mode mode = cBC1Ideal); -// -// This function manipulates global state, so it is not thread safe. -// You can call it multiple times to change the global BC1 approximation mode. -// Important: BC1/3 textures encoded using non-ideal BC1 approximation modes should only be sampled on parts from that vendor. -// If you encode for AMD, average error on AMD parts will go down, but average error on NVidia parts will go up and vice versa. -// If in doubt, encode in ideal BC1 mode. -// -// Call these functions to encode BC1-5: -// void rgbcx::encode_bc1(uint32_t level, void* pDst, const uint8_t* pPixels, bool allow_3color, bool use_transparent_texels_for_black); -// void rgbcx::encode_bc3(uint32_t level, void* pDst, const uint8_t* pPixels); -// void rgbcx::encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride = 4); -// void rgbcx::encode_bc5(void* pDst, const uint8_t* pPixels, uint32_t chan0 = 0, uint32_t chan1 = 1, uint32_t stride = 4); -// -// - level ranges from MIN_LEVEL to MAX_LEVEL. The higher the level, the slower the encoder goes, but the higher the average quality. -// levels [0,4] are fast and compete against stb_dxt (default and HIGHQUAL). The remaining levels compete against squish/NVTT/icbc and icbc HQ. -// If in doubt just use level 10, set allow_3color to true and use_transparent_texels_for_black to false, and adjust as needed. -// -// - pDst is a pointer to the 8-byte (BC1/4) or 16-byte (BC3/5) destination block. -// -// - pPixels is a pointer to the 32-bpp pixels, in either RGBX or RGBA format (R is first in memory). -// Alpha is always ignored by encode_bc1(). -// -// - allow_3color: If true the encoder will use 3-color blocks. This flag is ignored unless level is >= 5 (because lower levels compete against stb_dxt and it -// doesn't support 3-color blocks). Do not enable on BC3-5 textures. 3-color block usage slows down encoding. -// -// - use_transparent_texels_for_black: If true the encoder will use 3-color block transparent black pixels to code very dark or black texels. Your engine/shader -// MUST ignore the sampled alpha value for textures encoded in this mode. This is how NVidia's classic "nvdxt" encoder (used by many original Xbox titles) used -// to work by default on DXT1C textures. It increases average quality substantially (because dark texels/black are very common) and is highly recommended. Do -// not enable on BC3-5 textures. -// -// - stride is the source pixel stride, in bytes. It's typically 4. -// -// - chan0 and chan1 are the source channels. Typically they will be 0 and 1. -// -// All encoding and decoding functions are thread-safe. -// -// To reduce the compiled size of the encoder, set #define RGBCX_USE_SMALLER_TABLES to 1 before including this header. -// -#pragma once - -#include - -#include "BC1/BC1Block.h" -#include "BC3/BC3Block.h" -#include "BC4/BC4Block.h" -#include "BC5/BC5Block.h" -#include "Interpolator.h" - -// By default, the table used to accelerate cluster fit on 4 color blocks uses a 969x128 entry table. -// To reduce the executable size, set RGBCX_USE_SMALLER_TABLES to 1, which selects the smaller 969x32 entry table. -#ifndef RGBCX_USE_SMALLER_TABLES -#define RGBCX_USE_SMALLER_TABLES 0 -#endif - -namespace rgbcx { -enum class bc1_approx_mode { - // The default mode. No rounding for 4-color colors 2,3. My older tools/compressors use this mode. - // This matches the D3D10 docs on BC1. - cBC1Ideal = 0, - - // NVidia GPU mode. - cBC1NVidia = 1, - - // AMD GPU mode. - cBC1AMD = 2, - - // This mode matches AMD Compressonator's output. It rounds 4-color colors 2,3 (not 3-color color 2). - // This matches the D3D9 docs on DXT1. - cBC1IdealRound4 = 3 -}; - -// init() MUST be called once before using the BC1 encoder. -// This function may be called multiple times to change the BC1 approximation mode. -// This function initializes global state, so don't call it while other threads inside the encoder. -// Important: If you encode textures for a specific vendor's GPU's, beware that using that texture data on other GPU's may result in ugly artifacts. -// Encode to cBC1Ideal unless you know the texture data will only be deployed or used on a specific vendor's GPU. -void init(bc1_approx_mode mode = bc1_approx_mode::cBC1Ideal); - -// Optimally encodes a solid color block to BC1 format. -void encode_bc1_solid_block(void *pDst, uint32_t fr, uint32_t fg, uint32_t fb, bool allow_3color); - -// BC1 low-level API encoder flags. You can ignore this if you use the simple level API. -enum { - // Try to improve quality using the most likely total orderings. - // The total_orderings_to_try parameter will then control the number of total orderings to try for 4 color blocks, and the - // total_orderings_to_try3 parameter will control the number of total orderings to try for 3 color blocks (if they are enabled). - cEncodeBC1UseLikelyTotalOrderings = 2, - - // Use 2 least squares pass, instead of one (same as stb_dxt's HIGHQUAL option). - // Recommended if you're enabling cEncodeBC1UseLikelyTotalOrderings. - cEncodeBC1TwoLeastSquaresPasses = 4, - - // cEncodeBC1Use3ColorBlocksForBlackPixels allows the BC1 encoder to use 3-color blocks for blocks containing black or very dark pixels. - // You shader/engine MUST ignore the alpha channel on textures encoded with this flag. - // Average quality goes up substantially for my 100 texture corpus (~.5 dB), so it's worth using if you can. - // Note the BC1 encoder does not actually support transparency in 3-color mode. - // Don't set when encoding to BC3. - cEncodeBC1Use3ColorBlocksForBlackPixels = 8, - - // If cEncodeBC1Use3ColorBlocks is set, the encoder can use 3-color mode for a small but noticeable gain in average quality, but lower perf. - // If you also specify the cEncodeBC1UseLikelyTotalOrderings flag, set the total_orderings_to_try3 paramter to the number of total orderings to try. - // Don't set when encoding to BC3. - cEncodeBC1Use3ColorBlocks = 16, - - // cEncodeBC1Iterative will greatly increase encode time, but is very slightly higher quality. - // Same as squish's iterative cluster fit option. Not really worth the tiny boost in quality, unless you just don't care about perf. at all. - cEncodeBC1Iterative = 32, - - // cEncodeBC1BoundingBox enables a fast all-integer PCA approximation on 4-color blocks. - // At level 0 options (no other flags), this is ~15% faster, and higher *average* quality. - cEncodeBC1BoundingBox = 64, - - // Use a slightly lower quality, but ~30% faster MSE evaluation function for 4-color blocks. - cEncodeBC1UseFasterMSEEval = 128, - - // Examine all colors to compute selectors/MSE (slower than default) - cEncodeBC1UseFullMSEEval = 256, - - // Use 2D least squares+inset+optimal rounding (the method used in Humus's GPU texture encoding demo), instead of PCA. - // Around 18% faster, very slightly lower average quality to better (depends on the content). - cEncodeBC1Use2DLS = 512, - - // Use 6 power iterations vs. 4 for PCA. - cEncodeBC1Use6PowerIters = 2048, - - // Check all total orderings - *very* slow. The encoder is not designed to be used in this way. - cEncodeBC1Exhaustive = 8192, - - // Try 2 different ways of choosing the initial endpoints. - cEncodeBC1TryAllInitialEndponts = 16384, - - // Same as cEncodeBC1BoundingBox, but implemented using integer math (faster, slightly less quality) - cEncodeBC1BoundingBoxInt = 32768, - - // Try refining the final endpoints by examining nearby colors. - cEncodeBC1EndpointSearchRoundsShift = 22, - cEncodeBC1EndpointSearchRoundsMask = 1023U << cEncodeBC1EndpointSearchRoundsShift, -}; - -// DEFAULT_TOTAL_ORDERINGS_TO_TRY is around 3x faster than libsquish at slightly higher average quality. 10-16 is a good range to start to compete against -// libsquish. -const uint32_t DEFAULT_TOTAL_ORDERINGS_TO_TRY = 10; - -const uint32_t DEFAULT_TOTAL_ORDERINGS_TO_TRY3 = 1; - -// Encodes a 4x4 block of RGBX (X=ignored) pixels to BC1 format. -// This is the simplified interface for BC1 encoding, which accepts a level parameter and converts that to the best overall flags. -// The pixels are in RGBA format, where R is first in memory. The BC1 encoder completely ignores the alpha channel (i.e. there is no punchthrough alpha -// support). This is the recommended function to use for BC1 encoding, becuase it configures the encoder for you in the best possible way (on average). Note -// that the 3 color modes won't be used at all until level 5 or higher. No transparency supported, however if you set use_transparent_texels_for_black to true -// the encoder will use transparent selectors on very dark/black texels to reduce MSE. -const uint32_t MIN_LEVEL = 0, MAX_LEVEL = 18; -void encode_bc1(uint32_t level, void *pDst, const uint8_t *pPixels, bool allow_3color, bool use_transparent_texels_for_black); - -// Low-level interface for BC1 encoding. -// Always returns a 4 color block, unless cEncodeBC1Use3ColorBlocksForBlackPixels or cEncodeBC1Use3ColorBlock flags are specified. -// total_orderings_to_try controls the perf. vs. quality tradeoff on 4-color blocks when the cEncodeBC1UseLikelyTotalOrderings flag is used. It must range -// between [MIN_TOTAL_ORDERINGS, MAX_TOTAL_ORDERINGS4]. total_orderings_to_try3 controls the perf. vs. quality tradeoff on 3-color bocks when the -// cEncodeBC1UseLikelyTotalOrderings and the cEncodeBC1Use3ColorBlocks flags are used. Valid range is [0,MAX_TOTAL_ORDERINGS3] (0=disabled). -void encode_bc1(void *pDst, const uint8_t *pPixels, uint32_t flags = 0, uint32_t total_orderings_to_try = DEFAULT_TOTAL_ORDERINGS_TO_TRY, - uint32_t total_orderings_to_try3 = DEFAULT_TOTAL_ORDERINGS_TO_TRY3); - -// Encodes a 4x4 block of RGBA pixels to BC3 format. -// There are two encode_bc3() functions. -// The first is the recommended function, which accepts a level parameter. -// The second is a low-level version that allows fine control over BC1 encoding. -void encode_bc3(uint32_t level, BC3Block *pDst, const uint8_t *pPixels); -void encode_bc3(BC3Block *pDst, const uint8_t *pPixels, uint32_t flags = 0, uint32_t total_orderings_to_try = DEFAULT_TOTAL_ORDERINGS_TO_TRY); - -// Encodes a single channel to BC4. -// stride is the source pixel stride in bytes. -void encode_bc4(void *pDst, const uint8_t *pPixels, uint32_t stride = 4); - -// Encodes two channels to BC5. -// chan0/chan1 control which channels, stride is the source pixel stride in bytes. -void encode_bc5(BC5Block *pDst, const uint8_t *pPixels, uint32_t chan0 = 0, uint32_t chan1 = 1, uint32_t stride = 4); - -// Decompression functions. - -// Returns true if the block uses 3 color punchthrough alpha mode. -bool unpack_bc1(const void *pBlock_bits, void *pPixels, bool set_alpha = true, bc1_approx_mode mode = bc1_approx_mode::cBC1Ideal); - -void unpack_bc4(const void *pBlock_bits, uint8_t *pPixels, uint32_t stride = 4); - -// Returns true if the block uses 3 color punchthrough alpha mode. -bool unpack_bc3(const void *pBlock_bits, void *pPixels, bc1_approx_mode mode = bc1_approx_mode::cBC1Ideal); - -void unpack_bc5(const void *pBlock_bits, void *pPixels, uint32_t chan0 = 0, uint32_t chan1 = 1, uint32_t stride = 4); -} // namespace rgbcx - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/src/rgbcx/test/RedbrushAlpha.png b/src/rgbcx/test/RedbrushAlpha.png deleted file mode 100644 index ed3649d..0000000 Binary files a/src/rgbcx/test/RedbrushAlpha.png and /dev/null differ diff --git a/src/rgbcx/test/bc7decomp.cpp b/src/rgbcx/test/bc7decomp.cpp deleted file mode 100644 index 762a3d0..0000000 --- a/src/rgbcx/test/bc7decomp.cpp +++ /dev/null @@ -1,429 +0,0 @@ -// File: bc7decomp.c - Richard Geldreich, Jr. 3/31/2020 - MIT license or public domain (see end of file) -#pragma GCC diagnostic ignored "-Weverything" -#include "bc7decomp.h" -namespace bc7decomp -{ - -const uint32_t g_bc7_weights2[4] = { 0, 21, 43, 64 }; -const uint32_t g_bc7_weights3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 }; -const uint32_t g_bc7_weights4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; - -const uint8_t g_bc7_partition2[64 * 16] = -{ - 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1, 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1, 0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1, - 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1, 0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, - 0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1, 0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0, 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0, 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1, - 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0, 0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0, 0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0, 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, 0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0, 0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0, - 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, 0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0, 0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0, 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0, 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0, 0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1, 0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1, - 0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0, 0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0, 0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0, 0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1, 0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1, 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0, - 0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0, 0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0, 0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0, 0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0, 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0, - 0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1, 0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1, 0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1, 0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1, 0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0, 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0, 0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1 -}; - -const uint8_t g_bc7_partition3[64 * 16] = -{ - 0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2, 0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1, 0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1, 0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2, 0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2, 0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1, 0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1, - 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2, 0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2, 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2, 0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2, 0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2, 0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0, - 0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2, 0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0, 0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2, 0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1, 0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2, 0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1, 0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2, 0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0, - 0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0, 0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2, 0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0, 0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1, 0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2, 0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2, 0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1, 0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1, - 0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2, 0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1, 0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2, 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0, 0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0, 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0, 0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0, 0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1, - 0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1, 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1, 0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2, 0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1, 0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1, 0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1, 0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1, - 0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2, 0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1, 0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2, 0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2, 0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2, 0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2, 0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2, - 0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2, 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2, 0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2, 0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2, 0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1, 0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2, 0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2, 0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0, -}; - -const uint8_t g_bc7_table_anchor_index_second_subset[64] = { 15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15, 15, 2, 8, 2, 2, 8, 8,15, 2, 8, 2, 2, 8, 8, 2, 2, 15,15, 6, 8, 2, 8,15,15, 2, 8, 2, 2, 2,15,15, 6, 6, 2, 6, 8,15,15, 2, 2, 15,15,15,15,15, 2, 2,15 }; - -const uint8_t g_bc7_table_anchor_index_third_subset_1[64] = -{ - 3, 3,15,15, 8, 3,15,15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8,15, 3, 3, 6,10, 5, 8, 8, 6, 8, 5,15,15, 8,15, 3, 5, 6,10, 8,15, 15, 3,15, 5,15,15,15,15, 3,15, 5, 5, 5, 8, 5,10, 5,10, 8,13,15,12, 3, 3 -}; - -const uint8_t g_bc7_table_anchor_index_third_subset_2[64] = -{ - 15, 8, 8, 3,15,15, 3, 8, 15,15,15,15,15,15,15, 8, 15, 8,15, 3,15, 8,15, 8, 3,15, 6,10,15,15,10, 8, 15, 3,15,10,10, 8, 9,10, 6,15, 8,15, 3, 6, 6, 8, 15, 3,15,15,15,15,15,15, 15,15,15,15, 3,15,15, 8 -}; - -inline uint32_t read_bits32(const uint8_t* pBuf, uint32_t& bit_offset, uint32_t codesize) -{ - assert(codesize <= 32); - uint32_t bits = 0; - uint32_t total_bits = 0; - - while (total_bits < codesize) - { - uint32_t byte_bit_offset = bit_offset & 7; - uint32_t bits_to_read = std::min(codesize - total_bits, 8 - byte_bit_offset); - - uint32_t byte_bits = pBuf[bit_offset >> 3] >> byte_bit_offset; - byte_bits &= ((1 << bits_to_read) - 1); - - bits |= (byte_bits << total_bits); - - total_bits += bits_to_read; - bit_offset += bits_to_read; - } - - return bits; -} - -// BC7 mode 0-7 decompression. -// Instead of one monster routine to unpack all the BC7 modes, we're lumping the 3 subset, 2 subset, 1 subset, and dual plane modes together into simple shared routines. - -static inline uint32_t bc7_dequant(uint32_t val, uint32_t pbit, uint32_t val_bits) { assert(val < (1U << val_bits)); assert(pbit < 2); assert(val_bits >= 4 && val_bits <= 8); const uint32_t total_bits = val_bits + 1; val = (val << 1) | pbit; val <<= (8 - total_bits); val |= (val >> total_bits); assert(val <= 255); return val; } -static inline uint32_t bc7_dequant(uint32_t val, uint32_t val_bits) { assert(val < (1U << val_bits)); assert(val_bits >= 4 && val_bits <= 8); val <<= (8 - val_bits); val |= (val >> val_bits); assert(val <= 255); return val; } - -static inline uint32_t bc7_interp2(uint32_t l, uint32_t h, uint32_t w) { assert(w < 4); return (l * (64 - g_bc7_weights2[w]) + h * g_bc7_weights2[w] + 32) >> 6; } -static inline uint32_t bc7_interp3(uint32_t l, uint32_t h, uint32_t w) { assert(w < 8); return (l * (64 - g_bc7_weights3[w]) + h * g_bc7_weights3[w] + 32) >> 6; } -static inline uint32_t bc7_interp4(uint32_t l, uint32_t h, uint32_t w) { assert(w < 16); return (l * (64 - g_bc7_weights4[w]) + h * g_bc7_weights4[w] + 32) >> 6; } -static inline uint32_t bc7_interp(uint32_t l, uint32_t h, uint32_t w, uint32_t bits) -{ - assert(l <= 255 && h <= 255); - switch (bits) - { - case 2: return bc7_interp2(l, h, w); - case 3: return bc7_interp3(l, h, w); - case 4: return bc7_interp4(l, h, w); - default: - break; - } - return 0; -} - -bool unpack_bc7_mode0_2(uint32_t mode, const void* pBlock_bits, color_rgba* pPixels) -{ - //const uint32_t SUBSETS = 3; - const uint32_t ENDPOINTS = 6; - const uint32_t COMPS = 3; - const uint32_t WEIGHT_BITS = (mode == 0) ? 3 : 2; - const uint32_t ENDPOINT_BITS = (mode == 0) ? 4 : 5; - const uint32_t PBITS = (mode == 0) ? 6 : 0; - const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS; - - uint32_t bit_offset = 0; - const uint8_t* pBuf = static_cast(pBlock_bits); - - if (read_bits32(pBuf, bit_offset, mode + 1) != (1U << mode)) return false; - - const uint32_t part = read_bits32(pBuf, bit_offset, (mode == 0) ? 4 : 6); - - color_rgba endpoints[ENDPOINTS]; - for (uint32_t c = 0; c < COMPS; c++) - for (uint32_t e = 0; e < ENDPOINTS; e++) - endpoints[e][c] = (uint8_t)read_bits32(pBuf, bit_offset, ENDPOINT_BITS); - - uint32_t pbits[6]; - for (uint32_t p = 0; p < PBITS; p++) - pbits[p] = read_bits32(pBuf, bit_offset, 1); - - uint32_t weights[16]; - for (uint32_t i = 0; i < 16; i++) - weights[i] = read_bits32(pBuf, bit_offset, ((!i) || (i == g_bc7_table_anchor_index_third_subset_1[part]) || (i == g_bc7_table_anchor_index_third_subset_2[part])) ? (WEIGHT_BITS - 1) : WEIGHT_BITS); - - assert(bit_offset == 128); - - for (uint32_t e = 0; e < ENDPOINTS; e++) - for (uint32_t c = 0; c < 4; c++) - endpoints[e][c] = (uint8_t)((c == 3) ? 255 : (PBITS ? bc7_dequant(endpoints[e][c], pbits[e], ENDPOINT_BITS) : bc7_dequant(endpoints[e][c], ENDPOINT_BITS))); - - color_rgba block_colors[3][8]; - for (uint32_t s = 0; s < 3; s++) - for (uint32_t i = 0; i < WEIGHT_VALS; i++) - { - for (uint32_t c = 0; c < 3; c++) - block_colors[s][i][c] = (uint8_t)bc7_interp(endpoints[s * 2 + 0][c], endpoints[s * 2 + 1][c], i, WEIGHT_BITS); - block_colors[s][i][3] = 255; - } - - for (uint32_t i = 0; i < 16; i++) - pPixels[i] = block_colors[g_bc7_partition3[part * 16 + i]][weights[i]]; - - return true; -} - -bool unpack_bc7_mode1_3_7(uint32_t mode, const void* pBlock_bits, color_rgba* pPixels) -{ - //const uint32_t SUBSETS = 2; - const uint32_t ENDPOINTS = 4; - const uint32_t COMPS = (mode == 7) ? 4 : 3; - const uint32_t WEIGHT_BITS = (mode == 1) ? 3 : 2; - const uint32_t ENDPOINT_BITS = (mode == 7) ? 5 : ((mode == 1) ? 6 : 7); - const uint32_t PBITS = (mode == 1) ? 2 : 4; - const uint32_t SHARED_PBITS = (mode == 1) ? true : false; - const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS; - - uint32_t bit_offset = 0; - const uint8_t* pBuf = static_cast(pBlock_bits); - - if (read_bits32(pBuf, bit_offset, mode + 1) != (1U << mode)) return false; - - const uint32_t part = read_bits32(pBuf, bit_offset, 6); - - color_rgba endpoints[ENDPOINTS]; - for (uint32_t c = 0; c < COMPS; c++) - for (uint32_t e = 0; e < ENDPOINTS; e++) - endpoints[e][c] = (uint8_t)read_bits32(pBuf, bit_offset, ENDPOINT_BITS); - - uint32_t pbits[4]; - for (uint32_t p = 0; p < PBITS; p++) - pbits[p] = read_bits32(pBuf, bit_offset, 1); - - uint32_t weights[16]; - for (uint32_t i = 0; i < 16; i++) - weights[i] = read_bits32(pBuf, bit_offset, ((!i) || (i == g_bc7_table_anchor_index_second_subset[part])) ? (WEIGHT_BITS - 1) : WEIGHT_BITS); - - assert(bit_offset == 128); - - for (uint32_t e = 0; e < ENDPOINTS; e++) - for (uint32_t c = 0; c < 4; c++) - endpoints[e][c] = (uint8_t)((c == ((mode == 7U) ? 4U : 3U)) ? 255 : bc7_dequant(endpoints[e][c], pbits[SHARED_PBITS ? (e >> 1) : e], ENDPOINT_BITS)); - - color_rgba block_colors[2][8]; - for (uint32_t s = 0; s < 2; s++) - for (uint32_t i = 0; i < WEIGHT_VALS; i++) - { - for (uint32_t c = 0; c < COMPS; c++) - block_colors[s][i][c] = (uint8_t)bc7_interp(endpoints[s * 2 + 0][c], endpoints[s * 2 + 1][c], i, WEIGHT_BITS); - block_colors[s][i][3] = (COMPS == 3) ? 255 : block_colors[s][i][3]; - } - - for (uint32_t i = 0; i < 16; i++) - pPixels[i] = block_colors[g_bc7_partition2[part * 16 + i]][weights[i]]; - - return true; -} - -bool unpack_bc7_mode4_5(uint32_t mode, const void* pBlock_bits, color_rgba* pPixels) -{ - const uint32_t ENDPOINTS = 2; - const uint32_t COMPS = 4; - const uint32_t WEIGHT_BITS = 2; - const uint32_t A_WEIGHT_BITS = (mode == 4) ? 3 : 2; - const uint32_t ENDPOINT_BITS = (mode == 4) ? 5 : 7; - const uint32_t A_ENDPOINT_BITS = (mode == 4) ? 6 : 8; - //const uint32_t WEIGHT_VALS = 1 << WEIGHT_BITS; - //const uint32_t A_WEIGHT_VALS = 1 << A_WEIGHT_BITS; - - uint32_t bit_offset = 0; - const uint8_t* pBuf = static_cast(pBlock_bits); - - if (read_bits32(pBuf, bit_offset, mode + 1) != (1U << mode)) return false; - - const uint32_t comp_rot = read_bits32(pBuf, bit_offset, 2); - const uint32_t index_mode = (mode == 4) ? read_bits32(pBuf, bit_offset, 1) : 0; - - color_rgba endpoints[ENDPOINTS]; - for (uint32_t c = 0; c < COMPS; c++) - for (uint32_t e = 0; e < ENDPOINTS; e++) - endpoints[e][c] = (uint8_t)read_bits32(pBuf, bit_offset, (c == 3) ? A_ENDPOINT_BITS : ENDPOINT_BITS); - - const uint32_t weight_bits[2] = { index_mode ? A_WEIGHT_BITS : WEIGHT_BITS, index_mode ? WEIGHT_BITS : A_WEIGHT_BITS }; - - uint32_t weights[16], a_weights[16]; - - for (uint32_t i = 0; i < 16; i++) - (index_mode ? a_weights : weights)[i] = read_bits32(pBuf, bit_offset, weight_bits[index_mode] - ((!i) ? 1 : 0)); - - for (uint32_t i = 0; i < 16; i++) - (index_mode ? weights : a_weights)[i] = read_bits32(pBuf, bit_offset, weight_bits[1 - index_mode] - ((!i) ? 1 : 0)); - - assert(bit_offset == 128); - - for (uint32_t e = 0; e < ENDPOINTS; e++) - for (uint32_t c = 0; c < 4; c++) - endpoints[e][c] = (uint8_t)bc7_dequant(endpoints[e][c], (c == 3) ? A_ENDPOINT_BITS : ENDPOINT_BITS); - - color_rgba block_colors[8]; - for (uint32_t i = 0; i < (1U << weight_bits[0]); i++) - for (uint32_t c = 0; c < 3; c++) - block_colors[i][c] = (uint8_t)bc7_interp(endpoints[0][c], endpoints[1][c], i, weight_bits[0]); - - for (uint32_t i = 0; i < (1U << weight_bits[1]); i++) - block_colors[i][3] = (uint8_t)bc7_interp(endpoints[0][3], endpoints[1][3], i, weight_bits[1]); - - for (uint32_t i = 0; i < 16; i++) - { - pPixels[i] = block_colors[weights[i]]; - pPixels[i].a = block_colors[a_weights[i]].a; - if (comp_rot >= 1) - std::swap(pPixels[i].a, pPixels[i].m_comps[comp_rot - 1]); - } - - return true; -} - -struct bc7_mode_6 -{ - struct - { - uint64_t m_mode : 7; - uint64_t m_r0 : 7; - uint64_t m_r1 : 7; - uint64_t m_g0 : 7; - uint64_t m_g1 : 7; - uint64_t m_b0 : 7; - uint64_t m_b1 : 7; - uint64_t m_a0 : 7; - uint64_t m_a1 : 7; - uint64_t m_p0 : 1; - } m_lo; - - union - { - struct - { - uint64_t m_p1 : 1; - uint64_t m_s00 : 3; - uint64_t m_s10 : 4; - uint64_t m_s20 : 4; - uint64_t m_s30 : 4; - - uint64_t m_s01 : 4; - uint64_t m_s11 : 4; - uint64_t m_s21 : 4; - uint64_t m_s31 : 4; - - uint64_t m_s02 : 4; - uint64_t m_s12 : 4; - uint64_t m_s22 : 4; - uint64_t m_s32 : 4; - - uint64_t m_s03 : 4; - uint64_t m_s13 : 4; - uint64_t m_s23 : 4; - uint64_t m_s33 : 4; - - } m_hi; - - uint64_t m_hi_bits; - }; -}; - -bool unpack_bc7_mode6(const void *pBlock_bits, color_rgba *pPixels) -{ - static_assert(sizeof(bc7_mode_6) == 16, "sizeof(bc7_mode_6) == 16"); - - const bc7_mode_6 &block = *static_cast(pBlock_bits); - - if (block.m_lo.m_mode != (1 << 6)) - return false; - - const uint32_t r0 = (uint32_t)((block.m_lo.m_r0 << 1) | block.m_lo.m_p0); - const uint32_t g0 = (uint32_t)((block.m_lo.m_g0 << 1) | block.m_lo.m_p0); - const uint32_t b0 = (uint32_t)((block.m_lo.m_b0 << 1) | block.m_lo.m_p0); - const uint32_t a0 = (uint32_t)((block.m_lo.m_a0 << 1) | block.m_lo.m_p0); - const uint32_t r1 = (uint32_t)((block.m_lo.m_r1 << 1) | block.m_hi.m_p1); - const uint32_t g1 = (uint32_t)((block.m_lo.m_g1 << 1) | block.m_hi.m_p1); - const uint32_t b1 = (uint32_t)((block.m_lo.m_b1 << 1) | block.m_hi.m_p1); - const uint32_t a1 = (uint32_t)((block.m_lo.m_a1 << 1) | block.m_hi.m_p1); - - color_rgba vals[16]; - for (uint32_t i = 0; i < 16; i++) - { - const uint32_t w = g_bc7_weights4[i]; - const uint32_t iw = 64 - w; - vals[i].set_noclamp_rgba( - (r0 * iw + r1 * w + 32) >> 6, - (g0 * iw + g1 * w + 32) >> 6, - (b0 * iw + b1 * w + 32) >> 6, - (a0 * iw + a1 * w + 32) >> 6); - } - - pPixels[0] = vals[block.m_hi.m_s00]; - pPixels[1] = vals[block.m_hi.m_s10]; - pPixels[2] = vals[block.m_hi.m_s20]; - pPixels[3] = vals[block.m_hi.m_s30]; - - pPixels[4] = vals[block.m_hi.m_s01]; - pPixels[5] = vals[block.m_hi.m_s11]; - pPixels[6] = vals[block.m_hi.m_s21]; - pPixels[7] = vals[block.m_hi.m_s31]; - - pPixels[8] = vals[block.m_hi.m_s02]; - pPixels[9] = vals[block.m_hi.m_s12]; - pPixels[10] = vals[block.m_hi.m_s22]; - pPixels[11] = vals[block.m_hi.m_s32]; - - pPixels[12] = vals[block.m_hi.m_s03]; - pPixels[13] = vals[block.m_hi.m_s13]; - pPixels[14] = vals[block.m_hi.m_s23]; - pPixels[15] = vals[block.m_hi.m_s33]; - - return true; -} - -bool unpack_bc7(const void *pBlock, color_rgba *pPixels) -{ - const uint32_t first_byte = static_cast(pBlock)[0]; - - for (uint32_t mode = 0; mode <= 7; mode++) - { - if (first_byte & (1U << mode)) - { - switch (mode) - { - case 0: - case 2: - return unpack_bc7_mode0_2(mode, pBlock, pPixels); - case 1: - case 3: - case 7: - return unpack_bc7_mode1_3_7(mode, pBlock, pPixels); - case 4: - case 5: - return unpack_bc7_mode4_5(mode, pBlock, pPixels); - case 6: - return unpack_bc7_mode6(pBlock, pPixels); - default: - break; - } - } - } - - return false; -} - -} // namespace bc7decomp - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ - diff --git a/src/rgbcx/test/bc7decomp.h b/src/rgbcx/test/bc7decomp.h deleted file mode 100644 index 3c1e835..0000000 --- a/src/rgbcx/test/bc7decomp.h +++ /dev/null @@ -1,165 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace bc7decomp -{ - -enum eNoClamp { cNoClamp }; - -template inline S clamp(S value, S low, S high) { return (value < low) ? low : ((value > high) ? high : value); } - -class color_rgba -{ -public: - union - { - uint8_t m_comps[4]; - - struct - { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - }; - }; - - inline color_rgba() - { - static_assert(sizeof(*this) == 4, "sizeof(*this) != 4"); - } - - inline color_rgba(int y) - { - set(y); - } - - inline color_rgba(int y, int na) - { - set(y, na); - } - - inline color_rgba(int sr, int sg, int sb, int sa) - { - set(sr, sg, sb, sa); - } - - inline color_rgba(eNoClamp, int sr, int sg, int sb, int sa) - { - set_noclamp_rgba((uint8_t)sr, (uint8_t)sg, (uint8_t)sb, (uint8_t)sa); - } - - inline color_rgba& set_noclamp_y(int y) - { - m_comps[0] = (uint8_t)y; - m_comps[1] = (uint8_t)y; - m_comps[2] = (uint8_t)y; - m_comps[3] = (uint8_t)255; - return *this; - } - - inline color_rgba &set_noclamp_rgba(int sr, int sg, int sb, int sa) - { - m_comps[0] = (uint8_t)sr; - m_comps[1] = (uint8_t)sg; - m_comps[2] = (uint8_t)sb; - m_comps[3] = (uint8_t)sa; - return *this; - } - - inline color_rgba &set(int y) - { - m_comps[0] = static_cast(clamp(y, 0, 255)); - m_comps[1] = m_comps[0]; - m_comps[2] = m_comps[0]; - m_comps[3] = 255; - return *this; - } - - inline color_rgba &set(int y, int na) - { - m_comps[0] = static_cast(clamp(y, 0, 255)); - m_comps[1] = m_comps[0]; - m_comps[2] = m_comps[0]; - m_comps[3] = static_cast(clamp(na, 0, 255)); - return *this; - } - - inline color_rgba &set(int sr, int sg, int sb, int sa) - { - m_comps[0] = static_cast(clamp(sr, 0, 255)); - m_comps[1] = static_cast(clamp(sg, 0, 255)); - m_comps[2] = static_cast(clamp(sb, 0, 255)); - m_comps[3] = static_cast(clamp(sa, 0, 255)); - return *this; - } - - inline color_rgba &set_rgb(int sr, int sg, int sb) - { - m_comps[0] = static_cast(clamp(sr, 0, 255)); - m_comps[1] = static_cast(clamp(sg, 0, 255)); - m_comps[2] = static_cast(clamp(sb, 0, 255)); - return *this; - } - - inline color_rgba &set_rgb(const color_rgba &other) - { - r = other.r; - g = other.g; - b = other.b; - return *this; - } - - inline const uint8_t &operator[] (uint32_t index) const { assert(index < 4); return m_comps[index]; } - inline uint8_t &operator[] (uint32_t index) { assert(index < 4); return m_comps[index]; } - - inline void clear() - { - m_comps[0] = 0; - m_comps[1] = 0; - m_comps[2] = 0; - m_comps[3] = 0; - } - - inline bool operator== (const color_rgba &rhs) const - { - if (m_comps[0] != rhs.m_comps[0]) return false; - if (m_comps[1] != rhs.m_comps[1]) return false; - if (m_comps[2] != rhs.m_comps[2]) return false; - if (m_comps[3] != rhs.m_comps[3]) return false; - return true; - } - - inline bool operator!= (const color_rgba &rhs) const - { - return !(*this == rhs); - } - - inline bool operator<(const color_rgba &rhs) const - { - for (int i = 0; i < 4; i++) - { - if (m_comps[i] < rhs.m_comps[i]) - return true; - else if (m_comps[i] != rhs.m_comps[i]) - return false; - } - return false; - } - - inline int get_601_luma() const { return (19595U * m_comps[0] + 38470U * m_comps[1] + 7471U * m_comps[2] + 32768U) >> 16U; } - inline int get_709_luma() const { return (13938U * m_comps[0] + 46869U * m_comps[1] + 4729U * m_comps[2] + 32768U) >> 16U; } - inline int get_luma(bool luma_601) const { return luma_601 ? get_601_luma() : get_709_luma(); } - - static color_rgba comp_min(const color_rgba& a, const color_rgba& b) { return color_rgba(std::min(a[0], b[0]), std::min(a[1], b[1]), std::min(a[2], b[2]), std::min(a[3], b[3])); } - static color_rgba comp_max(const color_rgba& a, const color_rgba& b) { return color_rgba(std::max(a[0], b[0]), std::max(a[1], b[1]), std::max(a[2], b[2]), std::max(a[3], b[3])); } -}; - -bool unpack_bc7(const void *pBlock, color_rgba *pPixels); - -} // namespace bc7decomp diff --git a/src/rgbcx/test/bc7enc.c b/src/rgbcx/test/bc7enc.c deleted file mode 100644 index d2deb43..0000000 --- a/src/rgbcx/test/bc7enc.c +++ /dev/null @@ -1,2216 +0,0 @@ -// File: bc7enc.c - Richard Geldreich, Jr. 3/31/2020 - MIT license or public domain (see end of file) -// Currently supports modes 1, 6 for RGB blocks, and modes 5, 6, 7 for RGBA blocks. -// NOTE: This module is still a work in progress as of 3/31/2020. It needs to support more modes for RGB content. -#pragma GCC diagnostic ignored "-Weverything" - -#include "bc7enc.h" -#include -#include -#include -#include -#include - -// Helpers -static inline int32_t clampi(int32_t value, int32_t low, int32_t high) { if (value < low) value = low; else if (value > high) value = high; return value; } -static inline float clampf(float value, float low, float high) { if (value < low) value = low; else if (value > high) value = high; return value; } -static inline float saturate(float value) { return clampf(value, 0, 1.0f); } -static inline uint8_t minimumub(uint8_t a, uint8_t b) { return (a < b) ? a : b; } -static inline uint32_t minimumu(uint32_t a, uint32_t b) { return (a < b) ? a : b; } -static inline float minimumf(float a, float b) { return (a < b) ? a : b; } -static inline uint8_t maximumub(uint8_t a, uint8_t b) { return (a > b) ? a : b; } -static inline uint32_t maximumu(uint32_t a, uint32_t b) { return (a > b) ? a : b; } -static inline float maximumf(float a, float b) { return (a > b) ? a : b; } -static inline int squarei(int i) { return i * i; } -static inline float squaref(float i) { return i * i; } - -static inline int32_t iabs32(int32_t v) { uint32_t msk = v >> 31; return (v ^ msk) - msk; } -static inline void swapub(uint8_t* a, uint8_t* b) { uint8_t t = *a; *a = *b; *b = t; } -static inline void swapu(uint32_t* a, uint32_t* b) { uint32_t t = *a; *a = *b; *b = t; } -static inline void swapf(float* a, float* b) { float t = *a; *a = *b; *b = t; } - -typedef struct { uint8_t m_c[4]; } color_quad_u8; -typedef struct { float m_c[4]; } vec4F; - -static inline color_quad_u8 *color_quad_u8_set_clamped(color_quad_u8 *pRes, int32_t r, int32_t g, int32_t b, int32_t a) { pRes->m_c[0] = (uint8_t)clampi(r, 0, 255); pRes->m_c[1] = (uint8_t)clampi(g, 0, 255); pRes->m_c[2] = (uint8_t)clampi(b, 0, 255); pRes->m_c[3] = (uint8_t)clampi(a, 0, 255); return pRes; } -static inline color_quad_u8 *color_quad_u8_set(color_quad_u8 *pRes, int32_t r, int32_t g, int32_t b, int32_t a) { assert((uint32_t)(r | g | b | a) <= 255); pRes->m_c[0] = (uint8_t)r; pRes->m_c[1] = (uint8_t)g; pRes->m_c[2] = (uint8_t)b; pRes->m_c[3] = (uint8_t)a; return pRes; } -static inline bc7enc_bool color_quad_u8_notequals(const color_quad_u8 *pLHS, const color_quad_u8 *pRHS) { return (pLHS->m_c[0] != pRHS->m_c[0]) || (pLHS->m_c[1] != pRHS->m_c[1]) || (pLHS->m_c[2] != pRHS->m_c[2]) || (pLHS->m_c[3] != pRHS->m_c[3]); } -static inline vec4F *vec4F_set_scalar(vec4F *pV, float x) { pV->m_c[0] = x; pV->m_c[1] = x; pV->m_c[2] = x; pV->m_c[3] = x; return pV; } -static inline vec4F *vec4F_set(vec4F *pV, float x, float y, float z, float w) { pV->m_c[0] = x; pV->m_c[1] = y; pV->m_c[2] = z; pV->m_c[3] = w; return pV; } -static inline vec4F *vec4F_saturate_in_place(vec4F *pV) { pV->m_c[0] = saturate(pV->m_c[0]); pV->m_c[1] = saturate(pV->m_c[1]); pV->m_c[2] = saturate(pV->m_c[2]); pV->m_c[3] = saturate(pV->m_c[3]); return pV; } -static inline vec4F vec4F_saturate(const vec4F *pV) { vec4F res; res.m_c[0] = saturate(pV->m_c[0]); res.m_c[1] = saturate(pV->m_c[1]); res.m_c[2] = saturate(pV->m_c[2]); res.m_c[3] = saturate(pV->m_c[3]); return res; } -static inline vec4F vec4F_from_color(const color_quad_u8 *pC) { vec4F res; vec4F_set(&res, pC->m_c[0], pC->m_c[1], pC->m_c[2], pC->m_c[3]); return res; } -static inline vec4F vec4F_add(const vec4F *pLHS, const vec4F *pRHS) { vec4F res; vec4F_set(&res, pLHS->m_c[0] + pRHS->m_c[0], pLHS->m_c[1] + pRHS->m_c[1], pLHS->m_c[2] + pRHS->m_c[2], pLHS->m_c[3] + pRHS->m_c[3]); return res; } -static inline vec4F vec4F_sub(const vec4F *pLHS, const vec4F *pRHS) { vec4F res; vec4F_set(&res, pLHS->m_c[0] - pRHS->m_c[0], pLHS->m_c[1] - pRHS->m_c[1], pLHS->m_c[2] - pRHS->m_c[2], pLHS->m_c[3] - pRHS->m_c[3]); return res; } -static inline float vec4F_dot(const vec4F *pLHS, const vec4F *pRHS) { return pLHS->m_c[0] * pRHS->m_c[0] + pLHS->m_c[1] * pRHS->m_c[1] + pLHS->m_c[2] * pRHS->m_c[2] + pLHS->m_c[3] * pRHS->m_c[3]; } -static inline vec4F vec4F_mul(const vec4F *pLHS, float s) { vec4F res; vec4F_set(&res, pLHS->m_c[0] * s, pLHS->m_c[1] * s, pLHS->m_c[2] * s, pLHS->m_c[3] * s); return res; } -static inline vec4F *vec4F_normalize_in_place(vec4F *pV) { float s = pV->m_c[0] * pV->m_c[0] + pV->m_c[1] * pV->m_c[1] + pV->m_c[2] * pV->m_c[2] + pV->m_c[3] * pV->m_c[3]; if (s != 0.0f) { s = 1.0f / sqrtf(s); pV->m_c[0] *= s; pV->m_c[1] *= s; pV->m_c[2] *= s; pV->m_c[3] *= s; } return pV; } - -// Various BC7 tables -static const uint32_t g_bc7_weights2[4] = { 0, 21, 43, 64 }; -static const uint32_t g_bc7_weights3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 }; -static const uint32_t g_bc7_weights4[16] = { 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 }; -// Precomputed weight constants used during least fit determination. For each entry in g_bc7_weights[]: w * w, (1.0f - w) * w, (1.0f - w) * (1.0f - w), w -static const float g_bc7_weights2x[4 * 4] = { 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.107666f, 0.220459f, 0.451416f, 0.328125f, 0.451416f, 0.220459f, 0.107666f, 0.671875f, 1.000000f, 0.000000f, 0.000000f, 1.000000f }; -static const float g_bc7_weights3x[8 * 4] = { 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.019775f, 0.120850f, 0.738525f, 0.140625f, 0.079102f, 0.202148f, 0.516602f, 0.281250f, 0.177979f, 0.243896f, 0.334229f, 0.421875f, 0.334229f, 0.243896f, 0.177979f, 0.578125f, 0.516602f, 0.202148f, - 0.079102f, 0.718750f, 0.738525f, 0.120850f, 0.019775f, 0.859375f, 1.000000f, 0.000000f, 0.000000f, 1.000000f }; -static const float g_bc7_weights4x[16 * 4] = { 0.000000f, 0.000000f, 1.000000f, 0.000000f, 0.003906f, 0.058594f, 0.878906f, 0.062500f, 0.019775f, 0.120850f, 0.738525f, 0.140625f, 0.041260f, 0.161865f, 0.635010f, 0.203125f, 0.070557f, 0.195068f, 0.539307f, 0.265625f, 0.107666f, 0.220459f, - 0.451416f, 0.328125f, 0.165039f, 0.241211f, 0.352539f, 0.406250f, 0.219727f, 0.249023f, 0.282227f, 0.468750f, 0.282227f, 0.249023f, 0.219727f, 0.531250f, 0.352539f, 0.241211f, 0.165039f, 0.593750f, 0.451416f, 0.220459f, 0.107666f, 0.671875f, 0.539307f, 0.195068f, 0.070557f, 0.734375f, - 0.635010f, 0.161865f, 0.041260f, 0.796875f, 0.738525f, 0.120850f, 0.019775f, 0.859375f, 0.878906f, 0.058594f, 0.003906f, 0.937500f, 1.000000f, 0.000000f, 0.000000f, 1.000000f }; - -static const uint8_t g_bc7_partition1[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; -static const uint8_t g_bc7_partition2[64 * 16] = -{ - 0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1, 0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1, 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1, 0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1, 0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1, - 0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1, 0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1, 0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1, 0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1, - 0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1, 0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0, 0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0, 0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0, 0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0, 0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1, - 0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0, 0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0, 0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0, 0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0, 0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0, 0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, 0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0, 0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0, - 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, 0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1, 0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0, 0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0, 0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0, 0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0, 0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1, 0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1, - 0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0, 0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0, 0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0, 0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0, 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, 0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1, 0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1, 0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0, - 0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0, 0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0, 0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0, 0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0, 0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1, 0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0, 0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0, - 0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1, 0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1, 0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1, 0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1, 0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1, 0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0, 0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0, 0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1 -}; - -static const uint8_t g_bc7_partition3[64 * 16] = -{ - 0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2, 0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1, 0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1, 0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1, 0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2, 0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2, 0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1, 0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1, - 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2, 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2, 0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2, 0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2, 0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2, 0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2, 0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0, - 0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2, 0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0, 0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2, 0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1, 0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2, 0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1, 0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2, 0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0, - 0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0, 0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2, 0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0, 0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1, 0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2, 0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2, 0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1, 0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1, - 0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2, 0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1, 0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2, 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0, 0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0, 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0, 0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0, 0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1, - 0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1, 0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1, 0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2, 0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1, 0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1, 0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1, 0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1, - 0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2, 0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1, 0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2, 0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2, 0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2, 0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2, 0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2, 0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2, - 0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2, 0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2, 0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2, 0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2, 0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1, 0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2, 0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2, 0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0, -}; - -static const uint8_t g_bc7_table_anchor_index_third_subset_1[64] = -{ - 3, 3,15,15, 8, 3,15,15, 8, 8, 6, 6, 6, 5, 3, 3, 3, 3, 8,15, 3, 3, 6,10, 5, 8, 8, 6, 8, 5,15,15, 8,15, 3, 5, 6,10, 8,15, 15, 3,15, 5,15,15,15,15, 3,15, 5, 5, 5, 8, 5,10, 5,10, 8,13,15,12, 3, 3 -}; - -static const uint8_t g_bc7_table_anchor_index_third_subset_2[64] = -{ - 15, 8, 8, 3,15,15, 3, 8, 15,15,15,15,15,15,15, 8, 15, 8,15, 3,15, 8,15, 8, 3,15, 6,10,15,15,10, 8, 15, 3,15,10,10, 8, 9,10, 6,15, 8,15, 3, 6, 6, 8, 15, 3,15,15,15,15,15,15, 15,15,15,15, 3,15,15, 8 -}; - -static const uint8_t g_bc7_table_anchor_index_second_subset[64] = { 15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15, 15, 2, 8, 2, 2, 8, 8,15, 2, 8, 2, 2, 8, 8, 2, 2, 15,15, 6, 8, 2, 8,15,15, 2, 8, 2, 2, 2,15,15, 6, 6, 2, 6, 8,15,15, 2, 2, 15,15,15,15,15, 2, 2,15 }; -static const uint8_t g_bc7_num_subsets[8] = { 3, 2, 3, 2, 1, 1, 1, 2 }; -static const uint8_t g_bc7_partition_bits[8] = { 4, 6, 6, 6, 0, 0, 0, 6 }; -static const uint8_t g_bc7_color_index_bitcount[8] = { 3, 3, 2, 2, 2, 2, 4, 2 }; -static int get_bc7_color_index_size(int mode, int index_selection_bit) { return g_bc7_color_index_bitcount[mode] + index_selection_bit; } -static uint8_t g_bc7_alpha_index_bitcount[8] = { 0, 0, 0, 0, 3, 2, 4, 2 }; -static int get_bc7_alpha_index_size(int mode, int index_selection_bit) { return g_bc7_alpha_index_bitcount[mode] - index_selection_bit; } -static const uint8_t g_bc7_mode_has_p_bits[8] = { 1, 1, 0, 1, 0, 0, 1, 1 }; -static const uint8_t g_bc7_mode_has_shared_p_bits[8] = { 0, 1, 0, 0, 0, 0, 0, 0 }; -static const uint8_t g_bc7_color_precision_table[8] = { 4, 6, 5, 7, 5, 7, 7, 5 }; -static const int8_t g_bc7_alpha_precision_table[8] = { 0, 0, 0, 0, 6, 8, 7, 5 }; -static bc7enc_bool get_bc7_mode_has_seperate_alpha_selectors(int mode) { return (mode == 4) || (mode == 5); } - -typedef struct { uint16_t m_error; uint8_t m_lo; uint8_t m_hi; } endpoint_err; - -static endpoint_err g_bc7_mode_1_optimal_endpoints[256][2]; // [c][pbit] -static const uint32_t BC7ENC_MODE_1_OPTIMAL_INDEX = 2; - -static endpoint_err g_bc7_mode_7_optimal_endpoints[256][2][2]; // [c][pbit][hp][lp] -const uint32_t BC7E_MODE_7_OPTIMAL_INDEX = 1; - -// Initialize the lookup table used for optimal single color compression in mode 1. Must be called before encoding. -void bc7enc_compress_block_init() -{ - for (int c = 0; c < 256; c++) - { - for (uint32_t lp = 0; lp < 2; lp++) - { - endpoint_err best; - best.m_error = (uint16_t)UINT16_MAX; - for (uint32_t l = 0; l < 64; l++) - { - uint32_t low = ((l << 1) | lp) << 1; - low |= (low >> 7); - for (uint32_t h = 0; h < 64; h++) - { - uint32_t high = ((h << 1) | lp) << 1; - high |= (high >> 7); - const int k = (low * (64 - g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX]) + high * g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX] + 32) >> 6; - const int err = (k - c) * (k - c); - if (err < best.m_error) - { - best.m_error = (uint16_t)err; - best.m_lo = (uint8_t)l; - best.m_hi = (uint8_t)h; - } - } // h - } // l - g_bc7_mode_1_optimal_endpoints[c][lp] = best; - } // lp - } // c - - // Mode 7: 555.1 2-bit indices - for (int c = 0; c < 256; c++) - { - for (uint32_t hp = 0; hp < 2; hp++) - { - for (uint32_t lp = 0; lp < 2; lp++) - { - endpoint_err best; - best.m_error = (uint16_t)UINT16_MAX; - best.m_lo = 0; - best.m_hi = 0; - - for (uint32_t l = 0; l < 32; l++) - { - uint32_t low = ((l << 1) | lp) << 2; - low |= (low >> 6); - - for (uint32_t h = 0; h < 32; h++) - { - uint32_t high = ((h << 1) | hp) << 2; - high |= (high >> 6); - - const int k = (low * (64 - g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX]) + high * g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX] + 32) >> 6; - - const int err = (k - c) * (k - c); - if (err < best.m_error) - { - best.m_error = (uint16_t)err; - best.m_lo = (uint8_t)l; - best.m_hi = (uint8_t)h; - } - } // h - } // l - - g_bc7_mode_7_optimal_endpoints[c][hp][lp] = best; - - } // hp - - } // lp - - } // c -} - -static void compute_least_squares_endpoints_rgba(uint32_t N, const uint8_t *pSelectors, const vec4F *pSelector_weights, vec4F *pXl, vec4F *pXh, const color_quad_u8 *pColors) -{ - // Least squares using normal equations: http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf - // I did this in matrix form first, expanded out all the ops, then optimized it a bit. - float z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f; - float q00_r = 0.0f, q10_r = 0.0f, t_r = 0.0f; - float q00_g = 0.0f, q10_g = 0.0f, t_g = 0.0f; - float q00_b = 0.0f, q10_b = 0.0f, t_b = 0.0f; - float q00_a = 0.0f, q10_a = 0.0f, t_a = 0.0f; - for (uint32_t i = 0; i < N; i++) - { - const uint32_t sel = pSelectors[i]; - z00 += pSelector_weights[sel].m_c[0]; - z10 += pSelector_weights[sel].m_c[1]; - z11 += pSelector_weights[sel].m_c[2]; - float w = pSelector_weights[sel].m_c[3]; - q00_r += w * pColors[i].m_c[0]; t_r += pColors[i].m_c[0]; - q00_g += w * pColors[i].m_c[1]; t_g += pColors[i].m_c[1]; - q00_b += w * pColors[i].m_c[2]; t_b += pColors[i].m_c[2]; - q00_a += w * pColors[i].m_c[3]; t_a += pColors[i].m_c[3]; - } - - q10_r = t_r - q00_r; - q10_g = t_g - q00_g; - q10_b = t_b - q00_b; - q10_a = t_a - q00_a; - - z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (det != 0.0f) - det = 1.0f / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - pXl->m_c[0] = (float)(iz00 * q00_r + iz01 * q10_r); pXh->m_c[0] = (float)(iz10 * q00_r + iz11 * q10_r); - pXl->m_c[1] = (float)(iz00 * q00_g + iz01 * q10_g); pXh->m_c[1] = (float)(iz10 * q00_g + iz11 * q10_g); - pXl->m_c[2] = (float)(iz00 * q00_b + iz01 * q10_b); pXh->m_c[2] = (float)(iz10 * q00_b + iz11 * q10_b); - pXl->m_c[3] = (float)(iz00 * q00_a + iz01 * q10_a); pXh->m_c[3] = (float)(iz10 * q00_a + iz11 * q10_a); - - for (uint32_t c = 0; c < 4; c++) - { - if ((pXl->m_c[c] < 0.0f) || (pXh->m_c[c] > 255.0f)) - { - uint32_t lo_v = UINT32_MAX, hi_v = 0; - for (uint32_t i = 0; i < N; i++) - { - lo_v = minimumu(lo_v, pColors[i].m_c[c]); - hi_v = maximumu(hi_v, pColors[i].m_c[c]); - } - - if (lo_v == hi_v) - { - pXl->m_c[c] = (float)lo_v; - pXh->m_c[c] = (float)hi_v; - } - } - } -} - -static void compute_least_squares_endpoints_rgb(uint32_t N, const uint8_t *pSelectors, const vec4F *pSelector_weights, vec4F *pXl, vec4F *pXh, const color_quad_u8 *pColors) -{ - float z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f; - float q00_r = 0.0f, q10_r = 0.0f, t_r = 0.0f; - float q00_g = 0.0f, q10_g = 0.0f, t_g = 0.0f; - float q00_b = 0.0f, q10_b = 0.0f, t_b = 0.0f; - for (uint32_t i = 0; i < N; i++) - { - const uint32_t sel = pSelectors[i]; - z00 += pSelector_weights[sel].m_c[0]; - z10 += pSelector_weights[sel].m_c[1]; - z11 += pSelector_weights[sel].m_c[2]; - float w = pSelector_weights[sel].m_c[3]; - q00_r += w * pColors[i].m_c[0]; t_r += pColors[i].m_c[0]; - q00_g += w * pColors[i].m_c[1]; t_g += pColors[i].m_c[1]; - q00_b += w * pColors[i].m_c[2]; t_b += pColors[i].m_c[2]; - } - - q10_r = t_r - q00_r; - q10_g = t_g - q00_g; - q10_b = t_b - q00_b; - - z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (det != 0.0f) - det = 1.0f / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - pXl->m_c[0] = (float)(iz00 * q00_r + iz01 * q10_r); pXh->m_c[0] = (float)(iz10 * q00_r + iz11 * q10_r); - pXl->m_c[1] = (float)(iz00 * q00_g + iz01 * q10_g); pXh->m_c[1] = (float)(iz10 * q00_g + iz11 * q10_g); - pXl->m_c[2] = (float)(iz00 * q00_b + iz01 * q10_b); pXh->m_c[2] = (float)(iz10 * q00_b + iz11 * q10_b); - pXl->m_c[3] = 255.0f; pXh->m_c[3] = 255.0f; - - for (uint32_t c = 0; c < 3; c++) - { - if ((pXl->m_c[c] < 0.0f) || (pXh->m_c[c] > 255.0f)) - { - uint32_t lo_v = UINT32_MAX, hi_v = 0; - for (uint32_t i = 0; i < N; i++) - { - lo_v = minimumu(lo_v, pColors[i].m_c[c]); - hi_v = maximumu(hi_v, pColors[i].m_c[c]); - } - - if (lo_v == hi_v) - { - pXl->m_c[c] = (float)lo_v; - pXh->m_c[c] = (float)hi_v; - } - } - } -} - -static void compute_least_squares_endpoints_a(uint32_t N, const uint8_t* pSelectors, const vec4F* pSelector_weights, float* pXl, float* pXh, const color_quad_u8* pColors) -{ - // Least squares using normal equations: http://www.cs.cornell.edu/~bindel/class/cs3220-s12/notes/lec10.pdf - // I did this in matrix form first, expanded out all the ops, then optimized it a bit. - float z00 = 0.0f, z01 = 0.0f, z10 = 0.0f, z11 = 0.0f; - float q00_a = 0.0f, q10_a = 0.0f, t_a = 0.0f; - for (uint32_t i = 0; i < N; i++) - { - const uint32_t sel = pSelectors[i]; - - z00 += pSelector_weights[sel].m_c[0]; - z10 += pSelector_weights[sel].m_c[1]; - z11 += pSelector_weights[sel].m_c[2]; - - float w = pSelector_weights[sel].m_c[3]; - - q00_a += w * pColors[i].m_c[3]; t_a += pColors[i].m_c[3]; - } - - q10_a = t_a - q00_a; - - z01 = z10; - - float det = z00 * z11 - z01 * z10; - if (det != 0.0f) - det = 1.0f / det; - - float iz00, iz01, iz10, iz11; - iz00 = z11 * det; - iz01 = -z01 * det; - iz10 = -z10 * det; - iz11 = z00 * det; - - *pXl = (float)(iz00 * q00_a + iz01 * q10_a); *pXh = (float)(iz10 * q00_a + iz11 * q10_a); - - if ((*pXl < 0.0f) || (*pXh > 255.0f)) - { - uint32_t lo_v = UINT32_MAX, hi_v = 0; - for (uint32_t i = 0; i < N; i++) - { - lo_v = minimumu(lo_v, pColors[i].m_c[3]); - hi_v = maximumu(hi_v, pColors[i].m_c[3]); - } - - if (lo_v == hi_v) - { - *pXl = (float)lo_v; - *pXh = (float)hi_v; - } - } -} - -typedef struct -{ - uint32_t m_num_pixels; - const color_quad_u8 *m_pPixels; - uint32_t m_num_selector_weights; - const uint32_t *m_pSelector_weights; - const vec4F *m_pSelector_weightsx; - uint32_t m_comp_bits; - uint32_t m_weights[4]; - bc7enc_bool m_has_alpha; - bc7enc_bool m_has_pbits; - bc7enc_bool m_endpoints_share_pbit; - bc7enc_bool m_perceptual; -} color_cell_compressor_params; - -typedef struct -{ - uint64_t m_best_overall_err; - color_quad_u8 m_low_endpoint; - color_quad_u8 m_high_endpoint; - uint32_t m_pbits[2]; - uint8_t *m_pSelectors; - uint8_t *m_pSelectors_temp; -} color_cell_compressor_results; - -static inline color_quad_u8 scale_color(const color_quad_u8 *pC, const color_cell_compressor_params *pParams) -{ - color_quad_u8 results; - - const uint32_t n = pParams->m_comp_bits + (pParams->m_has_pbits ? 1 : 0); - assert((n >= 4) && (n <= 8)); - - for (uint32_t i = 0; i < 4; i++) - { - uint32_t v = pC->m_c[i] << (8 - n); - v |= (v >> n); - assert(v <= 255); - results.m_c[i] = (uint8_t)(v); - } - - return results; -} - -static inline uint64_t compute_color_distance_rgb(const color_quad_u8 *pE1, const color_quad_u8 *pE2, bc7enc_bool perceptual, const uint32_t weights[4]) -{ - int dr, dg, db; - - if (perceptual) - { - const int l1 = pE1->m_c[0] * 109 + pE1->m_c[1] * 366 + pE1->m_c[2] * 37; - const int cr1 = ((int)pE1->m_c[0] << 9) - l1; - const int cb1 = ((int)pE1->m_c[2] << 9) - l1; - const int l2 = pE2->m_c[0] * 109 + pE2->m_c[1] * 366 + pE2->m_c[2] * 37; - const int cr2 = ((int)pE2->m_c[0] << 9) - l2; - const int cb2 = ((int)pE2->m_c[2] << 9) - l2; - dr = (l1 - l2) >> 8; - dg = (cr1 - cr2) >> 8; - db = (cb1 - cb2) >> 8; - } - else - { - dr = (int)pE1->m_c[0] - (int)pE2->m_c[0]; - dg = (int)pE1->m_c[1] - (int)pE2->m_c[1]; - db = (int)pE1->m_c[2] - (int)pE2->m_c[2]; - } - - return weights[0] * (uint32_t)(dr * dr) + weights[1] * (uint32_t)(dg * dg) + weights[2] * (uint32_t)(db * db); -} - -static inline uint64_t compute_color_distance_rgba(const color_quad_u8 *pE1, const color_quad_u8 *pE2, bc7enc_bool perceptual, const uint32_t weights[4]) -{ - int da = (int)pE1->m_c[3] - (int)pE2->m_c[3]; - return compute_color_distance_rgb(pE1, pE2, perceptual, weights) + (weights[3] * (uint32_t)(da * da)); -} - -static uint64_t pack_mode1_to_one_color(const color_cell_compressor_params *pParams, color_cell_compressor_results *pResults, uint32_t r, uint32_t g, uint32_t b, uint8_t *pSelectors) -{ - uint32_t best_err = UINT_MAX; - uint32_t best_p = 0; - - for (uint32_t p = 0; p < 2; p++) - { - uint32_t err = g_bc7_mode_1_optimal_endpoints[r][p].m_error + g_bc7_mode_1_optimal_endpoints[g][p].m_error + g_bc7_mode_1_optimal_endpoints[b][p].m_error; - if (err < best_err) - { - best_err = err; - best_p = p; - if (!best_err) - break; - } - } - - const endpoint_err *pEr = &g_bc7_mode_1_optimal_endpoints[r][best_p]; - const endpoint_err *pEg = &g_bc7_mode_1_optimal_endpoints[g][best_p]; - const endpoint_err *pEb = &g_bc7_mode_1_optimal_endpoints[b][best_p]; - - color_quad_u8_set(&pResults->m_low_endpoint, pEr->m_lo, pEg->m_lo, pEb->m_lo, 0); - color_quad_u8_set(&pResults->m_high_endpoint, pEr->m_hi, pEg->m_hi, pEb->m_hi, 0); - pResults->m_pbits[0] = best_p; - pResults->m_pbits[1] = 0; - - memset(pSelectors, BC7ENC_MODE_1_OPTIMAL_INDEX, pParams->m_num_pixels); - - color_quad_u8 p; - for (uint32_t i = 0; i < 3; i++) - { - uint32_t low = ((pResults->m_low_endpoint.m_c[i] << 1) | pResults->m_pbits[0]) << 1; - low |= (low >> 7); - - uint32_t high = ((pResults->m_high_endpoint.m_c[i] << 1) | pResults->m_pbits[0]) << 1; - high |= (high >> 7); - - p.m_c[i] = (uint8_t)((low * (64 - g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX]) + high * g_bc7_weights3[BC7ENC_MODE_1_OPTIMAL_INDEX] + 32) >> 6); - } - p.m_c[3] = 255; - - uint64_t total_err = 0; - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - total_err += compute_color_distance_rgb(&p, &pParams->m_pPixels[i], pParams->m_perceptual, pParams->m_weights); - - pResults->m_best_overall_err = total_err; - - return total_err; -} - -static uint64_t pack_mode7_to_one_color(const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, uint32_t r, uint32_t g, uint32_t b, uint32_t a, - uint8_t* pSelectors, uint32_t num_pixels, const color_quad_u8* pPixels) -{ - uint32_t best_err = UINT_MAX; - uint32_t best_p = 0; - - for (uint32_t p = 0; p < 4; p++) - { - uint32_t hi_p = p >> 1; - uint32_t lo_p = p & 1; - uint32_t err = g_bc7_mode_7_optimal_endpoints[r][hi_p][lo_p].m_error + g_bc7_mode_7_optimal_endpoints[g][hi_p][lo_p].m_error + g_bc7_mode_7_optimal_endpoints[b][hi_p][lo_p].m_error + g_bc7_mode_7_optimal_endpoints[a][hi_p][lo_p].m_error; - if (err < best_err) - { - best_err = err; - best_p = p; - if (!best_err) - break; - } - } - - uint32_t best_hi_p = best_p >> 1; - uint32_t best_lo_p = best_p & 1; - - const endpoint_err* pEr = &g_bc7_mode_7_optimal_endpoints[r][best_hi_p][best_lo_p]; - const endpoint_err* pEg = &g_bc7_mode_7_optimal_endpoints[g][best_hi_p][best_lo_p]; - const endpoint_err* pEb = &g_bc7_mode_7_optimal_endpoints[b][best_hi_p][best_lo_p]; - const endpoint_err* pEa = &g_bc7_mode_7_optimal_endpoints[a][best_hi_p][best_lo_p]; - - color_quad_u8_set(&pResults->m_low_endpoint, pEr->m_lo, pEg->m_lo, pEb->m_lo, pEa->m_lo); - color_quad_u8_set(&pResults->m_high_endpoint, pEr->m_hi, pEg->m_hi, pEb->m_hi, pEa->m_hi); - pResults->m_pbits[0] = best_lo_p; - pResults->m_pbits[1] = best_hi_p; - - for (uint32_t i = 0; i < num_pixels; i++) - pSelectors[i] = BC7E_MODE_7_OPTIMAL_INDEX; - - color_quad_u8 p; - - for (uint32_t i = 0; i < 4; i++) - { - uint32_t low = (pResults->m_low_endpoint.m_c[i] << 1) | pResults->m_pbits[0]; - uint32_t high = (pResults->m_high_endpoint.m_c[i] << 1) | pResults->m_pbits[1]; - - low = (low << 2) | (low >> 6); - high = (high << 2) | (high >> 6); - - p.m_c[i] = (low * (64 - g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX]) + high * g_bc7_weights2[BC7E_MODE_7_OPTIMAL_INDEX] + 32) >> 6; - } - - uint64_t total_err = 0; - for (uint32_t i = 0; i < num_pixels; i++) - total_err += compute_color_distance_rgba(&p, &pPixels[i], pParams->m_perceptual, pParams->m_weights); - - pResults->m_best_overall_err = total_err; - - return total_err; -} - -static uint64_t evaluate_solution(const color_quad_u8 *pLow, const color_quad_u8 *pHigh, const uint32_t pbits[2], const color_cell_compressor_params *pParams, color_cell_compressor_results *pResults) -{ - color_quad_u8 quantMinColor = *pLow; - color_quad_u8 quantMaxColor = *pHigh; - - if (pParams->m_has_pbits) - { - uint32_t minPBit, maxPBit; - - if (pParams->m_endpoints_share_pbit) - maxPBit = minPBit = pbits[0]; - else - { - minPBit = pbits[0]; - maxPBit = pbits[1]; - } - - quantMinColor.m_c[0] = (uint8_t)((pLow->m_c[0] << 1) | minPBit); - quantMinColor.m_c[1] = (uint8_t)((pLow->m_c[1] << 1) | minPBit); - quantMinColor.m_c[2] = (uint8_t)((pLow->m_c[2] << 1) | minPBit); - quantMinColor.m_c[3] = (uint8_t)((pLow->m_c[3] << 1) | minPBit); - - quantMaxColor.m_c[0] = (uint8_t)((pHigh->m_c[0] << 1) | maxPBit); - quantMaxColor.m_c[1] = (uint8_t)((pHigh->m_c[1] << 1) | maxPBit); - quantMaxColor.m_c[2] = (uint8_t)((pHigh->m_c[2] << 1) | maxPBit); - quantMaxColor.m_c[3] = (uint8_t)((pHigh->m_c[3] << 1) | maxPBit); - } - - color_quad_u8 actualMinColor = scale_color(&quantMinColor, pParams); - color_quad_u8 actualMaxColor = scale_color(&quantMaxColor, pParams); - - const uint32_t N = pParams->m_num_selector_weights; - - color_quad_u8 weightedColors[16]; - weightedColors[0] = actualMinColor; - weightedColors[N - 1] = actualMaxColor; - - const uint32_t nc = pParams->m_has_alpha ? 4 : 3; - for (uint32_t i = 1; i < (N - 1); i++) - for (uint32_t j = 0; j < nc; j++) - weightedColors[i].m_c[j] = (uint8_t)((actualMinColor.m_c[j] * (64 - pParams->m_pSelector_weights[i]) + actualMaxColor.m_c[j] * pParams->m_pSelector_weights[i] + 32) >> 6); - - const int lr = actualMinColor.m_c[0]; - const int lg = actualMinColor.m_c[1]; - const int lb = actualMinColor.m_c[2]; - const int dr = actualMaxColor.m_c[0] - lr; - const int dg = actualMaxColor.m_c[1] - lg; - const int db = actualMaxColor.m_c[2] - lb; - - uint64_t total_err = 0; - - if (!pParams->m_perceptual) - { - if (pParams->m_has_alpha) - { - const int la = actualMinColor.m_c[3]; - const int da = actualMaxColor.m_c[3] - la; - - const float f = N / (float)(squarei(dr) + squarei(dg) + squarei(db) + squarei(da) + .00000125f); - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const color_quad_u8 *pC = &pParams->m_pPixels[i]; - int r = pC->m_c[0]; - int g = pC->m_c[1]; - int b = pC->m_c[2]; - int a = pC->m_c[3]; - - int best_sel = (int)((float)((r - lr) * dr + (g - lg) * dg + (b - lb) * db + (a - la) * da) * f + .5f); - best_sel = clampi(best_sel, 1, N - 1); - - uint64_t err0 = compute_color_distance_rgba(&weightedColors[best_sel - 1], pC, BC7ENC_FALSE, pParams->m_weights); - uint64_t err1 = compute_color_distance_rgba(&weightedColors[best_sel], pC, BC7ENC_FALSE, pParams->m_weights); - - if (err1 > err0) - { - err1 = err0; - --best_sel; - } - total_err += err1; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - else - { - const float f = N / (float)(squarei(dr) + squarei(dg) + squarei(db) + .00000125f); - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const color_quad_u8 *pC = &pParams->m_pPixels[i]; - int r = pC->m_c[0]; - int g = pC->m_c[1]; - int b = pC->m_c[2]; - - int sel = (int)((float)((r - lr) * dr + (g - lg) * dg + (b - lb) * db) * f + .5f); - sel = clampi(sel, 1, N - 1); - - uint64_t err0 = compute_color_distance_rgb(&weightedColors[sel - 1], pC, BC7ENC_FALSE, pParams->m_weights); - uint64_t err1 = compute_color_distance_rgb(&weightedColors[sel], pC, BC7ENC_FALSE, pParams->m_weights); - - int best_sel = sel; - uint64_t best_err = err1; - if (err0 < best_err) - { - best_err = err0; - best_sel = sel - 1; - } - - total_err += best_err; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - } - else - { - // TODO: This could be improved. - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint64_t best_err = UINT64_MAX; - uint32_t best_sel = 0; - - if (pParams->m_has_alpha) - { - for (uint32_t j = 0; j < N; j++) - { - uint64_t err = compute_color_distance_rgba(&weightedColors[j], &pParams->m_pPixels[i], BC7ENC_TRUE, pParams->m_weights); - if (err < best_err) - { - best_err = err; - best_sel = j; - } - } - } - else - { - for (uint32_t j = 0; j < N; j++) - { - uint64_t err = compute_color_distance_rgb(&weightedColors[j], &pParams->m_pPixels[i], BC7ENC_TRUE, pParams->m_weights); - if (err < best_err) - { - best_err = err; - best_sel = j; - } - } - } - - total_err += best_err; - - pResults->m_pSelectors_temp[i] = (uint8_t)best_sel; - } - } - - if (total_err < pResults->m_best_overall_err) - { - pResults->m_best_overall_err = total_err; - - pResults->m_low_endpoint = *pLow; - pResults->m_high_endpoint = *pHigh; - - pResults->m_pbits[0] = pbits[0]; - pResults->m_pbits[1] = pbits[1]; - - memcpy(pResults->m_pSelectors, pResults->m_pSelectors_temp, sizeof(pResults->m_pSelectors[0]) * pParams->m_num_pixels); - } - - return total_err; -} - -static void fixDegenerateEndpoints(uint32_t mode, color_quad_u8 *pTrialMinColor, color_quad_u8 *pTrialMaxColor, const vec4F *pXl, const vec4F *pXh, uint32_t iscale) -{ - //if ((mode == 1) || (mode == 7)) - if (mode == 1) - { - // fix degenerate case where the input collapses to a single colorspace voxel, and we loose all freedom (test with grayscale ramps) - for (uint32_t i = 0; i < 3; i++) - { - if (pTrialMinColor->m_c[i] == pTrialMaxColor->m_c[i]) - { - if (fabs(pXl->m_c[i] - pXh->m_c[i]) > 0.0f) - { - if (pTrialMinColor->m_c[i] > (iscale >> 1)) - { - if (pTrialMinColor->m_c[i] > 0) - pTrialMinColor->m_c[i]--; - else - if (pTrialMaxColor->m_c[i] < iscale) - pTrialMaxColor->m_c[i]++; - } - else - { - if (pTrialMaxColor->m_c[i] < iscale) - pTrialMaxColor->m_c[i]++; - else if (pTrialMinColor->m_c[i] > 0) - pTrialMinColor->m_c[i]--; - } - } - } - } - } -} - -static uint64_t find_optimal_solution(uint32_t mode, vec4F xl, vec4F xh, const color_cell_compressor_params *pParams, color_cell_compressor_results *pResults) -{ - vec4F_saturate_in_place(&xl); vec4F_saturate_in_place(&xh); - - if (pParams->m_has_pbits) - { - const int iscalep = (1 << (pParams->m_comp_bits + 1)) - 1; - const float scalep = (float)iscalep; - - const int32_t totalComps = pParams->m_has_alpha ? 4 : 3; - - uint32_t best_pbits[2]; - color_quad_u8 bestMinColor, bestMaxColor; - - if (!pParams->m_endpoints_share_pbit) - { - float best_err0 = 1e+9; - float best_err1 = 1e+9; - - for (int p = 0; p < 2; p++) - { - color_quad_u8 xMinColor, xMaxColor; - - // Notes: The pbit controls which quantization intervals are selected. - // total_levels=2^(comp_bits+1), where comp_bits=4 for mode 0, etc. - // pbit 0: v=(b*2)/(total_levels-1), pbit 1: v=(b*2+1)/(total_levels-1) where b is the component bin from [0,total_levels/2-1] and v is the [0,1] component value - // rearranging you get for pbit 0: b=floor(v*(total_levels-1)/2+.5) - // rearranging you get for pbit 1: b=floor((v*(total_levels-1)-1)/2+.5) - for (uint32_t c = 0; c < 4; c++) - { - xMinColor.m_c[c] = (uint8_t)(clampi(((int)((xl.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - xMaxColor.m_c[c] = (uint8_t)(clampi(((int)((xh.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - } - - color_quad_u8 scaledLow = scale_color(&xMinColor, pParams); - color_quad_u8 scaledHigh = scale_color(&xMaxColor, pParams); - - float err0 = 0, err1 = 0; - for (int i = 0; i < totalComps; i++) - { - err0 += squaref(scaledLow.m_c[i] - xl.m_c[i] * 255.0f); - err1 += squaref(scaledHigh.m_c[i] - xh.m_c[i] * 255.0f); - } - - if (err0 < best_err0) - { - best_err0 = err0; - best_pbits[0] = p; - - bestMinColor.m_c[0] = xMinColor.m_c[0] >> 1; - bestMinColor.m_c[1] = xMinColor.m_c[1] >> 1; - bestMinColor.m_c[2] = xMinColor.m_c[2] >> 1; - bestMinColor.m_c[3] = xMinColor.m_c[3] >> 1; - } - - if (err1 < best_err1) - { - best_err1 = err1; - best_pbits[1] = p; - - bestMaxColor.m_c[0] = xMaxColor.m_c[0] >> 1; - bestMaxColor.m_c[1] = xMaxColor.m_c[1] >> 1; - bestMaxColor.m_c[2] = xMaxColor.m_c[2] >> 1; - bestMaxColor.m_c[3] = xMaxColor.m_c[3] >> 1; - } - } - } - else - { - // Endpoints share pbits - float best_err = 1e+9; - - for (int p = 0; p < 2; p++) - { - color_quad_u8 xMinColor, xMaxColor; - for (uint32_t c = 0; c < 4; c++) - { - xMinColor.m_c[c] = (uint8_t)(clampi(((int)((xl.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - xMaxColor.m_c[c] = (uint8_t)(clampi(((int)((xh.m_c[c] * scalep - p) / 2.0f + .5f)) * 2 + p, p, iscalep - 1 + p)); - } - - color_quad_u8 scaledLow = scale_color(&xMinColor, pParams); - color_quad_u8 scaledHigh = scale_color(&xMaxColor, pParams); - - float err = 0; - for (int i = 0; i < totalComps; i++) - err += squaref((scaledLow.m_c[i] / 255.0f) - xl.m_c[i]) + squaref((scaledHigh.m_c[i] / 255.0f) - xh.m_c[i]); - - if (err < best_err) - { - best_err = err; - best_pbits[0] = p; - best_pbits[1] = p; - for (uint32_t j = 0; j < 4; j++) - { - bestMinColor.m_c[j] = xMinColor.m_c[j] >> 1; - bestMaxColor.m_c[j] = xMaxColor.m_c[j] >> 1; - } - } - } - } - - fixDegenerateEndpoints(mode, &bestMinColor, &bestMaxColor, &xl, &xh, iscalep >> 1); - - if ((pResults->m_best_overall_err == UINT64_MAX) || color_quad_u8_notequals(&bestMinColor, &pResults->m_low_endpoint) || color_quad_u8_notequals(&bestMaxColor, &pResults->m_high_endpoint) || (best_pbits[0] != pResults->m_pbits[0]) || (best_pbits[1] != pResults->m_pbits[1])) - evaluate_solution(&bestMinColor, &bestMaxColor, best_pbits, pParams, pResults); - } - else - { - const int iscale = (1 << pParams->m_comp_bits) - 1; - const float scale = (float)iscale; - - color_quad_u8 trialMinColor, trialMaxColor; - color_quad_u8_set_clamped(&trialMinColor, (int)(xl.m_c[0] * scale + .5f), (int)(xl.m_c[1] * scale + .5f), (int)(xl.m_c[2] * scale + .5f), (int)(xl.m_c[3] * scale + .5f)); - color_quad_u8_set_clamped(&trialMaxColor, (int)(xh.m_c[0] * scale + .5f), (int)(xh.m_c[1] * scale + .5f), (int)(xh.m_c[2] * scale + .5f), (int)(xh.m_c[3] * scale + .5f)); - - fixDegenerateEndpoints(mode, &trialMinColor, &trialMaxColor, &xl, &xh, iscale); - - if ((pResults->m_best_overall_err == UINT64_MAX) || color_quad_u8_notequals(&trialMinColor, &pResults->m_low_endpoint) || color_quad_u8_notequals(&trialMaxColor, &pResults->m_high_endpoint)) - evaluate_solution(&trialMinColor, &trialMaxColor, pResults->m_pbits, pParams, pResults); - } - - return pResults->m_best_overall_err; -} - -static uint64_t color_cell_compression(uint32_t mode, const color_cell_compressor_params *pParams, color_cell_compressor_results *pResults, const bc7enc_compress_block_params *pComp_params) -{ - assert((mode == 6) || (mode == 7) || (!pParams->m_has_alpha)); - - pResults->m_best_overall_err = UINT64_MAX; - - // If the partition's colors are all the same in mode 1, then just pack them as a single color. - if (mode == 1) - { - const uint32_t cr = pParams->m_pPixels[0].m_c[0], cg = pParams->m_pPixels[0].m_c[1], cb = pParams->m_pPixels[0].m_c[2]; - - bc7enc_bool allSame = BC7ENC_TRUE; - for (uint32_t i = 1; i < pParams->m_num_pixels; i++) - { - if ((cr != pParams->m_pPixels[i].m_c[0]) || (cg != pParams->m_pPixels[i].m_c[1]) || (cb != pParams->m_pPixels[i].m_c[2])) - { - allSame = BC7ENC_FALSE; - break; - } - } - - if (allSame) - return pack_mode1_to_one_color(pParams, pResults, cr, cg, cb, pResults->m_pSelectors); - } - else if (mode == 7) - { - const uint32_t cr = pParams->m_pPixels[0].m_c[0], cg = pParams->m_pPixels[0].m_c[1], cb = pParams->m_pPixels[0].m_c[2], ca = pParams->m_pPixels[0].m_c[3]; - - bc7enc_bool allSame = BC7ENC_TRUE; - for (uint32_t i = 1; i < pParams->m_num_pixels; i++) - { - if ((cr != pParams->m_pPixels[i].m_c[0]) || (cg != pParams->m_pPixels[i].m_c[1]) || (cb != pParams->m_pPixels[i].m_c[2]) || (ca != pParams->m_pPixels[i].m_c[3])) - { - allSame = BC7ENC_FALSE; - break; - } - } - - if (allSame) - return pack_mode7_to_one_color(pParams, pResults, cr, cg, cb, ca, pResults->m_pSelectors, pParams->m_num_pixels, pParams->m_pPixels); - } - - // Compute partition's mean color and principle axis. - vec4F meanColor, axis; - vec4F_set_scalar(&meanColor, 0.0f); - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - vec4F color = vec4F_from_color(&pParams->m_pPixels[i]); - meanColor = vec4F_add(&meanColor, &color); - } - - vec4F meanColorScaled = vec4F_mul(&meanColor, 1.0f / (float)(pParams->m_num_pixels)); - - meanColor = vec4F_mul(&meanColor, 1.0f / (float)(pParams->m_num_pixels * 255.0f)); - vec4F_saturate_in_place(&meanColor); - - if (pParams->m_has_alpha) - { - // Use incremental PCA for RGBA PCA, because it's simple. - vec4F_set_scalar(&axis, 0.0f); - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - vec4F color = vec4F_from_color(&pParams->m_pPixels[i]); - color = vec4F_sub(&color, &meanColorScaled); - vec4F a = vec4F_mul(&color, color.m_c[0]); - vec4F b = vec4F_mul(&color, color.m_c[1]); - vec4F c = vec4F_mul(&color, color.m_c[2]); - vec4F d = vec4F_mul(&color, color.m_c[3]); - vec4F n = i ? axis : color; - vec4F_normalize_in_place(&n); - axis.m_c[0] += vec4F_dot(&a, &n); - axis.m_c[1] += vec4F_dot(&b, &n); - axis.m_c[2] += vec4F_dot(&c, &n); - axis.m_c[3] += vec4F_dot(&d, &n); - } - vec4F_normalize_in_place(&axis); - } - else - { - // Use covar technique for RGB PCA, because it doesn't require per-pixel normalization. - float cov[6] = { 0, 0, 0, 0, 0, 0 }; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - const color_quad_u8 *pV = &pParams->m_pPixels[i]; - float r = pV->m_c[0] - meanColorScaled.m_c[0]; - float g = pV->m_c[1] - meanColorScaled.m_c[1]; - float b = pV->m_c[2] - meanColorScaled.m_c[2]; - cov[0] += r*r; cov[1] += r*g; cov[2] += r*b; cov[3] += g*g; cov[4] += g*b; cov[5] += b*b; - } - - float vfr = .9f, vfg = 1.0f, vfb = .7f; - for (uint32_t iter = 0; iter < 3; iter++) - { - float r = vfr*cov[0] + vfg*cov[1] + vfb*cov[2]; - float g = vfr*cov[1] + vfg*cov[3] + vfb*cov[4]; - float b = vfr*cov[2] + vfg*cov[4] + vfb*cov[5]; - - float m = maximumf(maximumf(fabsf(r), fabsf(g)), fabsf(b)); - if (m > 1e-10f) - { - m = 1.0f / m; - r *= m; g *= m; b *= m; - } - - vfr = r; vfg = g; vfb = b; - } - - float len = vfr*vfr + vfg*vfg + vfb*vfb; - if (len < 1e-10f) - vec4F_set_scalar(&axis, 0.0f); - else - { - len = 1.0f / sqrtf(len); - vfr *= len; vfg *= len; vfb *= len; - vec4F_set(&axis, vfr, vfg, vfb, 0); - } - } - - // TODO: Try picking the 2 colors with the largest projection onto the axis, instead of computing new colors along the axis. - - if (vec4F_dot(&axis, &axis) < .5f) - { - if (pParams->m_perceptual) - vec4F_set(&axis, .213f, .715f, .072f, pParams->m_has_alpha ? .715f : 0); - else - vec4F_set(&axis, 1.0f, 1.0f, 1.0f, pParams->m_has_alpha ? 1.0f : 0); - vec4F_normalize_in_place(&axis); - } - - float l = 1e+9f, h = -1e+9f; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - vec4F color = vec4F_from_color(&pParams->m_pPixels[i]); - - vec4F q = vec4F_sub(&color, &meanColorScaled); - float d = vec4F_dot(&q, &axis); - - l = minimumf(l, d); - h = maximumf(h, d); - } - - l *= (1.0f / 255.0f); - h *= (1.0f / 255.0f); - - vec4F b0 = vec4F_mul(&axis, l); - vec4F b1 = vec4F_mul(&axis, h); - vec4F c0 = vec4F_add(&meanColor, &b0); - vec4F c1 = vec4F_add(&meanColor, &b1); - vec4F minColor = vec4F_saturate(&c0); - vec4F maxColor = vec4F_saturate(&c1); - - vec4F whiteVec; - vec4F_set_scalar(&whiteVec, 1.0f); - - if (vec4F_dot(&minColor, &whiteVec) > vec4F_dot(&maxColor, &whiteVec)) - { -#if 0 - // Don't compile correctly with VC 2019 in release. - vec4F temp = minColor; - minColor = maxColor; - maxColor = temp; -#else - float a = minColor.m_c[0], b = minColor.m_c[1], c = minColor.m_c[2], d = minColor.m_c[3]; - minColor.m_c[0] = maxColor.m_c[0]; - minColor.m_c[1] = maxColor.m_c[1]; - minColor.m_c[2] = maxColor.m_c[2]; - minColor.m_c[3] = maxColor.m_c[3]; - maxColor.m_c[0] = a; - maxColor.m_c[1] = b; - maxColor.m_c[2] = c; - maxColor.m_c[3] = d; -#endif - } - - // First find a solution using the block's PCA. - if (!find_optimal_solution(mode, minColor, maxColor, pParams, pResults)) - return 0; - - if (pComp_params->m_try_least_squares) - { - // Now try to refine the solution using least squares by computing the optimal endpoints from the current selectors. - vec4F xl, xh; - vec4F_set_scalar(&xl, 0.0f); - vec4F_set_scalar(&xh, 0.0f); - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, pResults->m_pSelectors, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, pResults->m_pSelectors, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults)) - return 0; - } - - if (pComp_params->m_uber_level > 0) - { - // In uber level 1, try varying the selectors a little, somewhat like cluster fit would. First try incrementing the minimum selectors, - // then try decrementing the selectrors, then try both. - uint8_t selectors_temp[16], selectors_temp1[16]; - memcpy(selectors_temp, pResults->m_pSelectors, pParams->m_num_pixels); - - const int max_selector = pParams->m_num_selector_weights - 1; - - uint32_t min_sel = 16; - uint32_t max_sel = 0; - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - min_sel = minimumu(min_sel, sel); - max_sel = maximumu(max_sel, sel); - } - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - if ((sel == min_sel) && (sel < (pParams->m_num_selector_weights - 1))) - sel++; - selectors_temp1[i] = (uint8_t)sel; - } - - vec4F xl, xh; - vec4F_set_scalar(&xl, 0.0f); - vec4F_set_scalar(&xh, 0.0f); - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults)) - return 0; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - if ((sel == max_sel) && (sel > 0)) - sel--; - selectors_temp1[i] = (uint8_t)sel; - } - - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults)) - return 0; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - { - uint32_t sel = selectors_temp[i]; - if ((sel == min_sel) && (sel < (pParams->m_num_selector_weights - 1))) - sel++; - else if ((sel == max_sel) && (sel > 0)) - sel--; - selectors_temp1[i] = (uint8_t)sel; - } - - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults)) - return 0; - - // In uber levels 2+, try taking more advantage of endpoint extrapolation by scaling the selectors in one direction or another. - const uint32_t uber_err_thresh = (pParams->m_num_pixels * 56) >> 4; - if ((pComp_params->m_uber_level >= 2) && (pResults->m_best_overall_err > uber_err_thresh)) - { - const int Q = (pComp_params->m_uber_level >= 4) ? (pComp_params->m_uber_level - 2) : 1; - for (int ly = -Q; ly <= 1; ly++) - { - for (int hy = max_selector - 1; hy <= (max_selector + Q); hy++) - { - if ((ly == 0) && (hy == max_selector)) - continue; - - for (uint32_t i = 0; i < pParams->m_num_pixels; i++) - selectors_temp1[i] = (uint8_t)clampf(floorf((float)max_selector * ((float)selectors_temp[i] - (float)ly) / ((float)hy - (float)ly) + .5f), 0, (float)max_selector); - - //vec4F xl, xh; - vec4F_set_scalar(&xl, 0.0f); - vec4F_set_scalar(&xh, 0.0f); - if (pParams->m_has_alpha) - compute_least_squares_endpoints_rgba(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - else - compute_least_squares_endpoints_rgb(pParams->m_num_pixels, selectors_temp1, pParams->m_pSelector_weightsx, &xl, &xh, pParams->m_pPixels); - - xl = vec4F_mul(&xl, (1.0f / 255.0f)); - xh = vec4F_mul(&xh, (1.0f / 255.0f)); - - if (!find_optimal_solution(mode, xl, xh, pParams, pResults)) - return 0; - } - } - } - } - - if (mode == 1) - { - // Try encoding the partition as a single color by using the optimal singe colors tables to encode the block to its mean. - color_cell_compressor_results avg_results = *pResults; - const uint32_t r = (int)(.5f + meanColor.m_c[0] * 255.0f), g = (int)(.5f + meanColor.m_c[1] * 255.0f), b = (int)(.5f + meanColor.m_c[2] * 255.0f); - uint64_t avg_err = pack_mode1_to_one_color(pParams, &avg_results, r, g, b, pResults->m_pSelectors_temp); - if (avg_err < pResults->m_best_overall_err) - { - *pResults = avg_results; - memcpy(pResults->m_pSelectors, pResults->m_pSelectors_temp, sizeof(pResults->m_pSelectors[0]) * pParams->m_num_pixels); - pResults->m_best_overall_err = avg_err; - } - } - else if (mode == 7) - { - // Try encoding the partition as a single color by using the optimal singe colors tables to encode the block to its mean. - color_cell_compressor_results avg_results = *pResults; - const uint32_t r = (int)(.5f + meanColor.m_c[0] * 255.0f), g = (int)(.5f + meanColor.m_c[1] * 255.0f), b = (int)(.5f + meanColor.m_c[2] * 255.0f), a = (int)(.5f + meanColor.m_c[3] * 255.0f); - uint64_t avg_err = pack_mode7_to_one_color(pParams, &avg_results, r, g, b, a, pResults->m_pSelectors_temp, pParams->m_num_pixels, pParams->m_pPixels); - if (avg_err < pResults->m_best_overall_err) - { - *pResults = avg_results; - memcpy(pResults->m_pSelectors, pResults->m_pSelectors_temp, sizeof(pResults->m_pSelectors[0]) * pParams->m_num_pixels); - pResults->m_best_overall_err = avg_err; - } - } - - return pResults->m_best_overall_err; -} - -static uint64_t color_cell_compression_est_mode1(uint32_t num_pixels, const color_quad_u8 *pPixels, bc7enc_bool perceptual, uint32_t pweights[4], uint64_t best_err_so_far) -{ - // Find RGB bounds as an approximation of the block's principle axis - uint32_t lr = 255, lg = 255, lb = 255; - uint32_t hr = 0, hg = 0, hb = 0; - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_quad_u8 *pC = &pPixels[i]; - if (pC->m_c[0] < lr) lr = pC->m_c[0]; - if (pC->m_c[1] < lg) lg = pC->m_c[1]; - if (pC->m_c[2] < lb) lb = pC->m_c[2]; - if (pC->m_c[0] > hr) hr = pC->m_c[0]; - if (pC->m_c[1] > hg) hg = pC->m_c[1]; - if (pC->m_c[2] > hb) hb = pC->m_c[2]; - } - - color_quad_u8 lowColor; color_quad_u8_set(&lowColor, lr, lg, lb, 0); - color_quad_u8 highColor; color_quad_u8_set(&highColor, hr, hg, hb, 0); - - // Place endpoints at bbox diagonals and compute interpolated colors - const uint32_t N = 8; - color_quad_u8 weightedColors[8]; - - weightedColors[0] = lowColor; - weightedColors[N - 1] = highColor; - for (uint32_t i = 1; i < (N - 1); i++) - { - weightedColors[i].m_c[0] = (uint8_t)((lowColor.m_c[0] * (64 - g_bc7_weights3[i]) + highColor.m_c[0] * g_bc7_weights3[i] + 32) >> 6); - weightedColors[i].m_c[1] = (uint8_t)((lowColor.m_c[1] * (64 - g_bc7_weights3[i]) + highColor.m_c[1] * g_bc7_weights3[i] + 32) >> 6); - weightedColors[i].m_c[2] = (uint8_t)((lowColor.m_c[2] * (64 - g_bc7_weights3[i]) + highColor.m_c[2] * g_bc7_weights3[i] + 32) >> 6); - } - - // Compute dots and thresholds - const int ar = highColor.m_c[0] - lowColor.m_c[0]; - const int ag = highColor.m_c[1] - lowColor.m_c[1]; - const int ab = highColor.m_c[2] - lowColor.m_c[2]; - - int dots[8]; - for (uint32_t i = 0; i < N; i++) - dots[i] = weightedColors[i].m_c[0] * ar + weightedColors[i].m_c[1] * ag + weightedColors[i].m_c[2] * ab; - - int thresh[8 - 1]; - for (uint32_t i = 0; i < (N - 1); i++) - thresh[i] = (dots[i] + dots[i + 1] + 1) >> 1; - - uint64_t total_err = 0; - if (perceptual) - { - // Transform block's interpolated colors to YCbCr - int l1[8], cr1[8], cb1[8]; - for (int j = 0; j < 8; j++) - { - const color_quad_u8 *pE1 = &weightedColors[j]; - l1[j] = pE1->m_c[0] * 109 + pE1->m_c[1] * 366 + pE1->m_c[2] * 37; - cr1[j] = ((int)pE1->m_c[0] << 9) - l1[j]; - cb1[j] = ((int)pE1->m_c[2] << 9) - l1[j]; - } - - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_quad_u8 *pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[6]) - s = 7; - else if (d >= thresh[5]) - s = 6; - else if (d >= thresh[4]) - s = 5; - else if (d >= thresh[3]) - s = 4; - else if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const int l2 = pC->m_c[0] * 109 + pC->m_c[1] * 366 + pC->m_c[2] * 37; - const int cr2 = ((int)pC->m_c[0] << 9) - l2; - const int cb2 = ((int)pC->m_c[2] << 9) - l2; - - const int dl = (l1[s] - l2) >> 8; - const int dcr = (cr1[s] - cr2) >> 8; - const int dcb = (cb1[s] - cb2) >> 8; - - int ie = (pweights[0] * dl * dl) + (pweights[1] * dcr * dcr) + (pweights[2] * dcb * dcb); - - total_err += ie; - if (total_err > best_err_so_far) - break; - } - } - else - { - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_quad_u8 *pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[6]) - s = 7; - else if (d >= thresh[5]) - s = 6; - else if (d >= thresh[4]) - s = 5; - else if (d >= thresh[3]) - s = 4; - else if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const color_quad_u8 *pE1 = &weightedColors[s]; - - int dr = (int)pE1->m_c[0] - (int)pC->m_c[0]; - int dg = (int)pE1->m_c[1] - (int)pC->m_c[1]; - int db = (int)pE1->m_c[2] - (int)pC->m_c[2]; - - total_err += pweights[0] * (dr * dr) + pweights[1] * (dg * dg) + pweights[2] * (db * db); - if (total_err > best_err_so_far) - break; - } - } - - return total_err; -} - -static uint64_t color_cell_compression_est_mode7(uint32_t num_pixels, const color_quad_u8* pPixels, bc7enc_bool perceptual, uint32_t pweights[4], uint64_t best_err_so_far) -{ - // Find RGB bounds as an approximation of the block's principle axis - uint32_t lr = 255, lg = 255, lb = 255, la = 255; - uint32_t hr = 0, hg = 0, hb = 0, ha = 0; - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_quad_u8* pC = &pPixels[i]; - if (pC->m_c[0] < lr) lr = pC->m_c[0]; - if (pC->m_c[1] < lg) lg = pC->m_c[1]; - if (pC->m_c[2] < lb) lb = pC->m_c[2]; - if (pC->m_c[3] < la) la = pC->m_c[3]; - - if (pC->m_c[0] > hr) hr = pC->m_c[0]; - if (pC->m_c[1] > hg) hg = pC->m_c[1]; - if (pC->m_c[2] > hb) hb = pC->m_c[2]; - if (pC->m_c[3] > ha) ha = pC->m_c[3]; - } - - color_quad_u8 lowColor; color_quad_u8_set(&lowColor, lr, lg, lb, la); - color_quad_u8 highColor; color_quad_u8_set(&highColor, hr, hg, hb, ha); - - // Place endpoints at bbox diagonals and compute interpolated colors - const uint32_t N = 4; - color_quad_u8 weightedColors[4]; - - weightedColors[0] = lowColor; - weightedColors[N - 1] = highColor; - for (uint32_t i = 1; i < (N - 1); i++) - { - weightedColors[i].m_c[0] = (uint8_t)((lowColor.m_c[0] * (64 - g_bc7_weights2[i]) + highColor.m_c[0] * g_bc7_weights2[i] + 32) >> 6); - weightedColors[i].m_c[1] = (uint8_t)((lowColor.m_c[1] * (64 - g_bc7_weights2[i]) + highColor.m_c[1] * g_bc7_weights2[i] + 32) >> 6); - weightedColors[i].m_c[2] = (uint8_t)((lowColor.m_c[2] * (64 - g_bc7_weights2[i]) + highColor.m_c[2] * g_bc7_weights2[i] + 32) >> 6); - weightedColors[i].m_c[3] = (uint8_t)((lowColor.m_c[3] * (64 - g_bc7_weights2[i]) + highColor.m_c[3] * g_bc7_weights2[i] + 32) >> 6); - } - - // Compute dots and thresholds - const int ar = highColor.m_c[0] - lowColor.m_c[0]; - const int ag = highColor.m_c[1] - lowColor.m_c[1]; - const int ab = highColor.m_c[2] - lowColor.m_c[2]; - const int aa = highColor.m_c[3] - lowColor.m_c[3]; - - int dots[4]; - for (uint32_t i = 0; i < N; i++) - dots[i] = weightedColors[i].m_c[0] * ar + weightedColors[i].m_c[1] * ag + weightedColors[i].m_c[2] * ab + weightedColors[i].m_c[3] * aa; - - int thresh[4 - 1]; - for (uint32_t i = 0; i < (N - 1); i++) - thresh[i] = (dots[i] + dots[i + 1] + 1) >> 1; - - uint64_t total_err = 0; - if (perceptual) - { - // Transform block's interpolated colors to YCbCr - int l1[4], cr1[4], cb1[4]; - for (int j = 0; j < 4; j++) - { - const color_quad_u8* pE1 = &weightedColors[j]; - l1[j] = pE1->m_c[0] * 109 + pE1->m_c[1] * 366 + pE1->m_c[2] * 37; - cr1[j] = ((int)pE1->m_c[0] << 9) - l1[j]; - cb1[j] = ((int)pE1->m_c[2] << 9) - l1[j]; - } - - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_quad_u8* pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2] + aa * pC->m_c[3]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const int l2 = pC->m_c[0] * 109 + pC->m_c[1] * 366 + pC->m_c[2] * 37; - const int cr2 = ((int)pC->m_c[0] << 9) - l2; - const int cb2 = ((int)pC->m_c[2] << 9) - l2; - - const int dl = (l1[s] - l2) >> 8; - const int dcr = (cr1[s] - cr2) >> 8; - const int dcb = (cb1[s] - cb2) >> 8; - - const int dca = (int)pC->m_c[3] - (int)weightedColors[s].m_c[3]; - - int ie = (pweights[0] * dl * dl) + (pweights[1] * dcr * dcr) + (pweights[2] * dcb * dcb) + (pweights[3] * dca * dca); - - total_err += ie; - if (total_err > best_err_so_far) - break; - } - } - else - { - for (uint32_t i = 0; i < num_pixels; i++) - { - const color_quad_u8* pC = &pPixels[i]; - - int d = ar * pC->m_c[0] + ag * pC->m_c[1] + ab * pC->m_c[2] + aa * pC->m_c[3]; - - // Find approximate selector - uint32_t s = 0; - if (d >= thresh[2]) - s = 3; - else if (d >= thresh[1]) - s = 2; - else if (d >= thresh[0]) - s = 1; - - // Compute error - const color_quad_u8* pE1 = &weightedColors[s]; - - int dr = (int)pE1->m_c[0] - (int)pC->m_c[0]; - int dg = (int)pE1->m_c[1] - (int)pC->m_c[1]; - int db = (int)pE1->m_c[2] - (int)pC->m_c[2]; - int da = (int)pE1->m_c[3] - (int)pC->m_c[3]; - - total_err += pweights[0] * (dr * dr) + pweights[1] * (dg * dg) + pweights[2] * (db * db) + pweights[3] * (da * da); - if (total_err > best_err_so_far) - break; - } - } - - return total_err; -} - -// This table contains bitmasks indicating which "key" partitions must be best ranked before this partition is worth evaluating. -// We first rank the best/most used 14 partitions (sorted by usefulness), record the best one found as the key partition, then use -// that to control the other partitions to evaluate. The quality loss is ~.08 dB RGB PSNR, the perf gain is up to ~11% (at uber level 0). -static const uint32_t g_partition_predictors[35] = -{ - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - (1 << 1) | (1 << 2) | (1 << 8), - (1 << 1) | (1 << 3) | (1 << 7), - UINT32_MAX, - UINT32_MAX, - (1 << 2) | (1 << 8) | (1 << 16), - (1 << 7) | (1 << 3) | (1 << 15), - UINT32_MAX, - (1 << 8) | (1 << 14) | (1 << 16), - (1 << 7) | (1 << 14) | (1 << 15), - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - (1 << 14) | (1 << 15), - (1 << 16) | (1 << 22) | (1 << 14), - (1 << 17) | (1 << 24) | (1 << 14), - (1 << 2) | (1 << 14) | (1 << 15) | (1 << 1), - UINT32_MAX, - (1 << 1) | (1 << 3) | (1 << 14) | (1 << 16) | (1 << 22), - UINT32_MAX, - (1 << 1) | (1 << 2) | (1 << 15) | (1 << 17) | (1 << 24), - (1 << 1) | (1 << 3) | (1 << 22), - UINT32_MAX, - UINT32_MAX, - UINT32_MAX, - (1 << 14) | (1 << 15) | (1 << 16) | (1 << 17), - UINT32_MAX, - UINT32_MAX, - (1 << 1) | (1 << 2) | (1 << 3) | (1 << 27) | (1 << 4) | (1 << 24), - (1 << 14) | (1 << 15) | (1 << 16) | (1 << 11) | (1 << 17) | (1 << 27) -}; - -// Estimate the partition used by modes 1/7. This scans through each partition and computes an approximate error for each. -static uint32_t estimate_partition(const color_quad_u8 *pPixels, const bc7enc_compress_block_params *pComp_params, uint32_t pweights[4], uint32_t mode) -{ - const uint32_t total_partitions = minimumu(pComp_params->m_max_partitions_mode, BC7ENC_MAX_PARTITIONS1); - if (total_partitions <= 1) - return 0; - - uint64_t best_err = UINT64_MAX; - uint32_t best_partition = 0; - - // Partition order sorted by usage frequency across a large test corpus. Pattern 34 (checkerboard) must appear in slot 34. - // Using a sorted order allows the user to decrease the # of partitions to scan with minimal loss in quality. - static const uint8_t s_sorted_partition_order[64] = - { - 1 - 1, 14 - 1, 2 - 1, 3 - 1, 16 - 1, 15 - 1, 11 - 1, 17 - 1, - 4 - 1, 24 - 1, 27 - 1, 7 - 1, 8 - 1, 22 - 1, 20 - 1, 30 - 1, - 9 - 1, 5 - 1, 10 - 1, 21 - 1, 6 - 1, 32 - 1, 23 - 1, 18 - 1, - 19 - 1, 12 - 1, 13 - 1, 31 - 1, 25 - 1, 26 - 1, 29 - 1, 28 - 1, - 33 - 1, 34 - 1, 35 - 1, 46 - 1, 47 - 1, 52 - 1, 50 - 1, 51 - 1, - 49 - 1, 39 - 1, 40 - 1, 38 - 1, 54 - 1, 53 - 1, 55 - 1, 37 - 1, - 58 - 1, 59 - 1, 56 - 1, 42 - 1, 41 - 1, 43 - 1, 44 - 1, 60 - 1, - 45 - 1, 57 - 1, 48 - 1, 36 - 1, 61 - 1, 64 - 1, 63 - 1, 62 - 1 - }; - - assert(s_sorted_partition_order[34] == 34); - - int best_key_partition = 0; - - for (uint32_t partition_iter = 0; (partition_iter < total_partitions) && (best_err > 0); partition_iter++) - { - const uint32_t partition = s_sorted_partition_order[partition_iter]; - - // Check to see if we should bother evaluating this partition at all, depending on the best partition found from the first 14. - if (pComp_params->m_mode_partition_estimation_filterbank) - { - if ((partition_iter >= 14) && (partition_iter <= 34)) - { - const uint32_t best_key_partition_bitmask = 1 << (best_key_partition + 1); - if ((g_partition_predictors[partition] & best_key_partition_bitmask) == 0) - { - if (partition_iter == 34) - break; - - continue; - } - } - } - - const uint8_t *pPartition = &g_bc7_partition2[partition * 16]; - - color_quad_u8 subset_colors[2][16]; - uint32_t subset_total_colors[2] = { 0, 0 }; - for (uint32_t index = 0; index < 16; index++) - subset_colors[pPartition[index]][subset_total_colors[pPartition[index]]++] = pPixels[index]; - - uint64_t total_subset_err = 0; - for (uint32_t subset = 0; (subset < 2) && (total_subset_err < best_err); subset++) - { - if (mode == 7) - total_subset_err += color_cell_compression_est_mode7(subset_total_colors[subset], &subset_colors[subset][0], pComp_params->m_perceptual, pweights, best_err); - else - total_subset_err += color_cell_compression_est_mode1(subset_total_colors[subset], &subset_colors[subset][0], pComp_params->m_perceptual, pweights, best_err); - } - - if (total_subset_err < best_err) - { - best_err = total_subset_err; - best_partition = partition; - } - - // If the checkerboard pattern doesn't get the highest ranking vs. the previous (lower frequency) patterns, then just stop now because statistically the subsequent patterns won't do well either. - if ((partition == 34) && (best_partition != 34)) - break; - - if (partition_iter == 13) - best_key_partition = best_partition; - - } // partition - - return best_partition; -} - -static void set_block_bits(uint8_t *pBytes, uint32_t val, uint32_t num_bits, uint32_t *pCur_ofs) -{ - assert((num_bits <= 32) && (val < (1ULL << num_bits))); - while (num_bits) - { - const uint32_t n = minimumu(8 - (*pCur_ofs & 7), num_bits); - pBytes[*pCur_ofs >> 3] |= (uint8_t)(val << (*pCur_ofs & 7)); - val >>= n; - num_bits -= n; - *pCur_ofs += n; - } - assert(*pCur_ofs <= 128); -} - -typedef struct -{ - uint32_t m_mode; - uint32_t m_partition; - uint8_t m_selectors[16]; - uint8_t m_alpha_selectors[16]; - color_quad_u8 m_low[3]; - color_quad_u8 m_high[3]; - uint32_t m_pbits[3][2]; - uint32_t m_rotation; - uint32_t m_index_selector; -} bc7_optimization_results; - -static void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults) -{ - assert(pResults->m_index_selector <= 1); - assert(pResults->m_rotation <= 3); - - const uint32_t best_mode = pResults->m_mode; - - const uint32_t total_subsets = g_bc7_num_subsets[best_mode]; - const uint32_t total_partitions = 1 << g_bc7_partition_bits[best_mode]; - //const uint32_t num_rotations = 1 << g_bc7_rotation_bits[best_mode]; - //const uint32_t num_index_selectors = (best_mode == 4) ? 2 : 1; - - const uint8_t* pPartition; - if (total_subsets == 1) - pPartition = &g_bc7_partition1[0]; - else if (total_subsets == 2) - pPartition = &g_bc7_partition2[pResults->m_partition * 16]; - else - pPartition = &g_bc7_partition3[pResults->m_partition * 16]; - - uint8_t color_selectors[16]; - memcpy(color_selectors, pResults->m_selectors, 16); - - uint8_t alpha_selectors[16]; - memcpy(alpha_selectors, pResults->m_alpha_selectors, 16); - - color_quad_u8 low[3], high[3]; - memcpy(low, pResults->m_low, sizeof(low)); - memcpy(high, pResults->m_high, sizeof(high)); - - uint32_t pbits[3][2]; - memcpy(pbits, pResults->m_pbits, sizeof(pbits)); - - int anchor[3] = { -1, -1, -1 }; - - for (uint32_t k = 0; k < total_subsets; k++) - { - uint32_t anchor_index = 0; - if (k) - { - if ((total_subsets == 3) && (k == 1)) - anchor_index = g_bc7_table_anchor_index_third_subset_1[pResults->m_partition]; - else if ((total_subsets == 3) && (k == 2)) - anchor_index = g_bc7_table_anchor_index_third_subset_2[pResults->m_partition]; - else - anchor_index = g_bc7_table_anchor_index_second_subset[pResults->m_partition]; - } - - anchor[k] = anchor_index; - - const uint32_t color_index_bits = get_bc7_color_index_size(best_mode, pResults->m_index_selector); - const uint32_t num_color_indices = 1 << color_index_bits; - - if (color_selectors[anchor_index] & (num_color_indices >> 1)) - { - for (uint32_t i = 0; i < 16; i++) - if (pPartition[i] == k) - color_selectors[i] = (uint8_t)((num_color_indices - 1) - color_selectors[i]); - - if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) - { - for (uint32_t q = 0; q < 3; q++) - { - uint8_t t = low[k].m_c[q]; - low[k].m_c[q] = high[k].m_c[q]; - high[k].m_c[q] = t; - } - } - else - { - color_quad_u8 tmp = low[k]; - low[k] = high[k]; - high[k] = tmp; - } - - if (!g_bc7_mode_has_shared_p_bits[best_mode]) - { - uint32_t t = pbits[k][0]; - pbits[k][0] = pbits[k][1]; - pbits[k][1] = t; - } - } - - if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) - { - const uint32_t alpha_index_bits = get_bc7_alpha_index_size(best_mode, pResults->m_index_selector); - const uint32_t num_alpha_indices = 1 << alpha_index_bits; - - if (alpha_selectors[anchor_index] & (num_alpha_indices >> 1)) - { - for (uint32_t i = 0; i < 16; i++) - if (pPartition[i] == k) - alpha_selectors[i] = (uint8_t)((num_alpha_indices - 1) - alpha_selectors[i]); - - uint8_t t = low[k].m_c[3]; - low[k].m_c[3] = high[k].m_c[3]; - high[k].m_c[3] = t; - } - } - } - - uint8_t* pBlock_bytes = (uint8_t*)(pBlock); - memset(pBlock_bytes, 0, BC7ENC_BLOCK_SIZE); - - uint32_t cur_bit_ofs = 0; - set_block_bits(pBlock_bytes, 1 << best_mode, best_mode + 1, &cur_bit_ofs); - - if ((best_mode == 4) || (best_mode == 5)) - set_block_bits(pBlock_bytes, pResults->m_rotation, 2, &cur_bit_ofs); - - if (best_mode == 4) - set_block_bits(pBlock_bytes, pResults->m_index_selector, 1, &cur_bit_ofs); - - if (total_partitions > 1) - set_block_bits(pBlock_bytes, pResults->m_partition, (total_partitions == 64) ? 6 : 4, &cur_bit_ofs); - - const uint32_t total_comps = (best_mode >= 4) ? 4 : 3; - for (uint32_t comp = 0; comp < total_comps; comp++) - { - for (uint32_t subset = 0; subset < total_subsets; subset++) - { - set_block_bits(pBlock_bytes, low[subset].m_c[comp], (comp == 3) ? g_bc7_alpha_precision_table[best_mode] : g_bc7_color_precision_table[best_mode], &cur_bit_ofs); - set_block_bits(pBlock_bytes, high[subset].m_c[comp], (comp == 3) ? g_bc7_alpha_precision_table[best_mode] : g_bc7_color_precision_table[best_mode], &cur_bit_ofs); - } - } - - if (g_bc7_mode_has_p_bits[best_mode]) - { - for (uint32_t subset = 0; subset < total_subsets; subset++) - { - set_block_bits(pBlock_bytes, pbits[subset][0], 1, &cur_bit_ofs); - if (!g_bc7_mode_has_shared_p_bits[best_mode]) - set_block_bits(pBlock_bytes, pbits[subset][1], 1, &cur_bit_ofs); - } - } - - for (uint32_t y = 0; y < 4; y++) - { - for (uint32_t x = 0; x < 4; x++) - { - int idx = x + y * 4; - - uint32_t n = pResults->m_index_selector ? get_bc7_alpha_index_size(best_mode, pResults->m_index_selector) : get_bc7_color_index_size(best_mode, pResults->m_index_selector); - - if ((idx == anchor[0]) || (idx == anchor[1]) || (idx == anchor[2])) - n--; - - set_block_bits(pBlock_bytes, pResults->m_index_selector ? alpha_selectors[idx] : color_selectors[idx], n, &cur_bit_ofs); - } - } - - if (get_bc7_mode_has_seperate_alpha_selectors(best_mode)) - { - for (uint32_t y = 0; y < 4; y++) - { - for (uint32_t x = 0; x < 4; x++) - { - int idx = x + y * 4; - - uint32_t n = pResults->m_index_selector ? get_bc7_color_index_size(best_mode, pResults->m_index_selector) : get_bc7_alpha_index_size(best_mode, pResults->m_index_selector); - - if ((idx == anchor[0]) || (idx == anchor[1]) || (idx == anchor[2])) - n--; - - set_block_bits(pBlock_bytes, pResults->m_index_selector ? color_selectors[idx] : alpha_selectors[idx], n, &cur_bit_ofs); - } - } - } - - assert(cur_bit_ofs == 128); -} - -static void handle_alpha_block_mode5(const color_quad_u8* pPixels, const bc7enc_compress_block_params* pComp_params, color_cell_compressor_params* pParams, uint32_t lo_a, uint32_t hi_a, bc7_optimization_results* pOpt_results5, uint64_t* pMode5_err, uint64_t* pMode5_alpha_err) -{ - pParams->m_pSelector_weights = g_bc7_weights2; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights2x; - pParams->m_num_selector_weights = 4; - - pParams->m_comp_bits = 7; - pParams->m_has_pbits = BC7ENC_FALSE; - pParams->m_endpoints_share_pbit = BC7ENC_FALSE; - pParams->m_has_alpha = BC7ENC_FALSE; - - pParams->m_perceptual = pComp_params->m_perceptual; - - pParams->m_num_pixels = 16; - pParams->m_pPixels = pPixels; - - color_cell_compressor_results results5; - results5.m_pSelectors = pOpt_results5->m_selectors; - - uint8_t selectors_temp[16]; - results5.m_pSelectors_temp = selectors_temp; - - *pMode5_err = color_cell_compression(5, pParams, &results5, pComp_params); - assert(*pMode5_err == results5.m_best_overall_err); - - pOpt_results5->m_low[0] = results5.m_low_endpoint; - pOpt_results5->m_high[0] = results5.m_high_endpoint; - - if (lo_a == hi_a) - { - *pMode5_alpha_err = 0; - pOpt_results5->m_low[0].m_c[3] = (uint8_t)lo_a; - pOpt_results5->m_high[0].m_c[3] = (uint8_t)hi_a; - memset(pOpt_results5->m_alpha_selectors, 0, sizeof(pOpt_results5->m_alpha_selectors)); - } - else - { - *pMode5_alpha_err = UINT64_MAX; - - const uint32_t total_passes = (pComp_params->m_uber_level >= 1) ? 3 : 2; - for (uint32_t pass = 0; pass < total_passes; pass++) - { - int32_t vals[4]; - vals[0] = lo_a; - vals[3] = hi_a; - - const int32_t w_s1 = 21, w_s2 = 43; - vals[1] = (vals[0] * (64 - w_s1) + vals[3] * w_s1 + 32) >> 6; - vals[2] = (vals[0] * (64 - w_s2) + vals[3] * w_s2 + 32) >> 6; - - uint8_t trial_alpha_selectors[16]; - - uint64_t trial_alpha_err = 0; - for (uint32_t i = 0; i < 16; i++) - { - const int32_t a = pParams->m_pPixels[i].m_c[3]; - - int s = 0; - int32_t be = iabs32(a - vals[0]); - int e = iabs32(a - vals[1]); if (e < be) { be = e; s = 1; } - e = iabs32(a - vals[2]); if (e < be) { be = e; s = 2; } - e = iabs32(a - vals[3]); if (e < be) { be = e; s = 3; } - - trial_alpha_selectors[i] = (uint8_t)s; - - uint32_t a_err = (uint32_t)(be * be) * pParams->m_weights[3]; - - trial_alpha_err += a_err; - } - - if (trial_alpha_err < *pMode5_alpha_err) - { - *pMode5_alpha_err = trial_alpha_err; - pOpt_results5->m_low[0].m_c[3] = (uint8_t)lo_a; - pOpt_results5->m_high[0].m_c[3] = (uint8_t)hi_a; - memcpy(pOpt_results5->m_alpha_selectors, trial_alpha_selectors, sizeof(pOpt_results5->m_alpha_selectors)); - } - - if (pass != (total_passes - 1U)) - { - float xl, xh; - compute_least_squares_endpoints_a(16, trial_alpha_selectors, (const vec4F*)g_bc7_weights2x, &xl, &xh, pParams->m_pPixels); - - uint32_t new_lo_a = clampi((int)floor(xl + .5f), 0, 255); - uint32_t new_hi_a = clampi((int)floor(xh + .5f), 0, 255); - if (new_lo_a > new_hi_a) - swapu(&new_lo_a, &new_hi_a); - - if ((new_lo_a == lo_a) && (new_hi_a == hi_a)) - break; - - lo_a = new_lo_a; - hi_a = new_hi_a; - } - } - - *pMode5_err += *pMode5_alpha_err; - } -} - -static void handle_alpha_block(void *pBlock, const color_quad_u8 *pPixels, const bc7enc_compress_block_params *pComp_params, color_cell_compressor_params *pParams) -{ - pParams->m_pSelector_weights = g_bc7_weights4; - pParams->m_pSelector_weightsx = (const vec4F *)g_bc7_weights4x; - pParams->m_num_selector_weights = 16; - pParams->m_comp_bits = 7; - pParams->m_has_pbits = BC7ENC_TRUE; - pParams->m_has_alpha = BC7ENC_TRUE; - pParams->m_perceptual = pComp_params->m_perceptual; - pParams->m_num_pixels = 16; - pParams->m_pPixels = pPixels; - - bc7_optimization_results opt_results6, opt_results5, opt_results7; - - color_cell_compressor_results results6; - results6.m_pSelectors = opt_results6.m_selectors; - uint8_t selectors_temp[16]; - results6.m_pSelectors_temp = selectors_temp; - - uint64_t best_err = color_cell_compression(6, pParams, &results6, pComp_params); - uint32_t best_mode = 6; - - if ((best_err > 0) && (pComp_params->m_use_mode5_for_alpha)) - { - uint32_t lo_a = 255, hi_a = 0; - for (uint32_t i = 0; i < 16; i++) - { - uint32_t a = pPixels[i].m_c[3]; - lo_a = minimumu(lo_a, a); - hi_a = maximumu(hi_a, a); - } - - uint64_t mode5_err, mode5_alpha_err; - handle_alpha_block_mode5(pPixels, pComp_params, pParams, lo_a, hi_a, &opt_results5, &mode5_err, &mode5_alpha_err); - - if (mode5_err < best_err) - { - best_err = mode5_err; - best_mode = 5; - } - } - - if ((best_err > 0) && (pComp_params->m_use_mode7_for_alpha)) - { - const uint32_t trial_partition = estimate_partition(pPixels, pComp_params, pParams->m_weights, 7); - - pParams->m_pSelector_weights = g_bc7_weights2; - pParams->m_pSelector_weightsx = (const vec4F*)g_bc7_weights2x; - pParams->m_num_selector_weights = 4; - pParams->m_comp_bits = 5; - pParams->m_has_pbits = BC7ENC_TRUE; - pParams->m_endpoints_share_pbit = BC7ENC_FALSE; - pParams->m_has_alpha = BC7ENC_TRUE; - - const uint8_t* pPartition = &g_bc7_partition2[trial_partition * 16]; - - color_quad_u8 subset_colors[2][16]; - - uint32_t subset_total_colors7[2] = { 0, 0 }; - - uint8_t subset_pixel_index7[2][16]; - uint8_t subset_selectors7[2][16]; - color_cell_compressor_results subset_results7[2]; - - for (uint32_t idx = 0; idx < 16; idx++) - { - const uint32_t p = pPartition[idx]; - subset_colors[p][subset_total_colors7[p]] = pPixels[idx]; - subset_pixel_index7[p][subset_total_colors7[p]] = (uint8_t)idx; - subset_total_colors7[p]++; - } - - uint64_t trial_err = 0; - for (uint32_t subset = 0; subset < 2; subset++) - { - pParams->m_num_pixels = subset_total_colors7[subset]; - pParams->m_pPixels = &subset_colors[subset][0]; - - color_cell_compressor_results* pResults = &subset_results7[subset]; - pResults->m_pSelectors = &subset_selectors7[subset][0]; - pResults->m_pSelectors_temp = selectors_temp; - uint64_t err = color_cell_compression(7, pParams, pResults, pComp_params); - trial_err += err; - if (trial_err > best_err) - break; - - } // subset - - if (trial_err < best_err) - { - best_err = trial_err; - best_mode = 7; - opt_results7.m_mode = 7; - opt_results7.m_partition = trial_partition; - opt_results7.m_index_selector = 0; - opt_results7.m_rotation = 0; - for (uint32_t subset = 0; subset < 2; subset++) - { - for (uint32_t i = 0; i < subset_total_colors7[subset]; i++) - opt_results7.m_selectors[subset_pixel_index7[subset][i]] = subset_selectors7[subset][i]; - opt_results7.m_low[subset] = subset_results7[subset].m_low_endpoint; - opt_results7.m_high[subset] = subset_results7[subset].m_high_endpoint; - opt_results7.m_pbits[subset][0] = subset_results7[subset].m_pbits[0]; - opt_results7.m_pbits[subset][1] = subset_results7[subset].m_pbits[1]; - } - } - } - - if (best_mode == 7) - { - encode_bc7_block(pBlock, &opt_results7); - } - else if (best_mode == 5) - { - opt_results5.m_mode = 5; - opt_results5.m_partition = 0; - opt_results5.m_rotation = 0; - opt_results5.m_index_selector = 0; - - encode_bc7_block(pBlock, &opt_results5); - } - else if (best_mode == 6) - { - opt_results6.m_mode = 6; - opt_results6.m_partition = 0; - opt_results6.m_low[0] = results6.m_low_endpoint; - opt_results6.m_high[0] = results6.m_high_endpoint; - opt_results6.m_pbits[0][0] = results6.m_pbits[0]; - opt_results6.m_pbits[0][1] = results6.m_pbits[1]; - opt_results6.m_rotation = 0; - opt_results6.m_index_selector = 0; - - encode_bc7_block(pBlock, &opt_results6); - } -} - -static void handle_opaque_block(void *pBlock, const color_quad_u8 *pPixels, const bc7enc_compress_block_params *pComp_params, color_cell_compressor_params *pParams) -{ - uint8_t selectors_temp[16]; - - // Mode 6 - bc7_optimization_results opt_results; - - pParams->m_pSelector_weights = g_bc7_weights4; - pParams->m_pSelector_weightsx = (const vec4F *)g_bc7_weights4x; - pParams->m_num_selector_weights = 16; - pParams->m_comp_bits = 7; - pParams->m_has_pbits = BC7ENC_TRUE; - pParams->m_endpoints_share_pbit = BC7ENC_FALSE; - pParams->m_perceptual = pComp_params->m_perceptual; - pParams->m_num_pixels = 16; - pParams->m_pPixels = pPixels; - pParams->m_has_alpha = BC7ENC_FALSE; - - color_cell_compressor_results results6; - results6.m_pSelectors = opt_results.m_selectors; - results6.m_pSelectors_temp = selectors_temp; - - uint64_t best_err = color_cell_compression(6, pParams, &results6, pComp_params); - - opt_results.m_mode = 6; - opt_results.m_partition = 0; - opt_results.m_low[0] = results6.m_low_endpoint; - opt_results.m_high[0] = results6.m_high_endpoint; - opt_results.m_pbits[0][0] = results6.m_pbits[0]; - opt_results.m_pbits[0][1] = results6.m_pbits[1]; - opt_results.m_index_selector = 0; - opt_results.m_rotation = 0; - - // Mode 1 - if ((best_err > 0) && (pComp_params->m_max_partitions_mode > 0)) - { - const uint32_t trial_partition = estimate_partition(pPixels, pComp_params, pParams->m_weights, 1); - - pParams->m_pSelector_weights = g_bc7_weights3; - pParams->m_pSelector_weightsx = (const vec4F *)g_bc7_weights3x; - pParams->m_num_selector_weights = 8; - pParams->m_comp_bits = 6; - pParams->m_has_pbits = BC7ENC_TRUE; - pParams->m_endpoints_share_pbit = BC7ENC_TRUE; - - const uint8_t *pPartition = &g_bc7_partition2[trial_partition * 16]; - - color_quad_u8 subset_colors[2][16]; - - uint32_t subset_total_colors1[2] = { 0, 0 }; - - uint8_t subset_pixel_index1[2][16]; - uint8_t subset_selectors1[2][16]; - color_cell_compressor_results subset_results1[2]; - - for (uint32_t idx = 0; idx < 16; idx++) - { - const uint32_t p = pPartition[idx]; - subset_colors[p][subset_total_colors1[p]] = pPixels[idx]; - subset_pixel_index1[p][subset_total_colors1[p]] = (uint8_t)idx; - subset_total_colors1[p]++; - } - - uint64_t trial_err = 0; - for (uint32_t subset = 0; subset < 2; subset++) - { - pParams->m_num_pixels = subset_total_colors1[subset]; - pParams->m_pPixels = &subset_colors[subset][0]; - - color_cell_compressor_results *pResults = &subset_results1[subset]; - pResults->m_pSelectors = &subset_selectors1[subset][0]; - pResults->m_pSelectors_temp = selectors_temp; - uint64_t err = color_cell_compression(1, pParams, pResults, pComp_params); - - trial_err += err; - if (trial_err > best_err) - break; - - } // subset - - if (trial_err < best_err) - { - best_err = trial_err; - opt_results.m_mode = 1; - opt_results.m_partition = trial_partition; - for (uint32_t subset = 0; subset < 2; subset++) - { - for (uint32_t i = 0; i < subset_total_colors1[subset]; i++) - opt_results.m_selectors[subset_pixel_index1[subset][i]] = subset_selectors1[subset][i]; - opt_results.m_low[subset] = subset_results1[subset].m_low_endpoint; - opt_results.m_high[subset] = subset_results1[subset].m_high_endpoint; - opt_results.m_pbits[subset][0] = subset_results1[subset].m_pbits[0]; - } - } - } - - encode_bc7_block(pBlock, &opt_results); -} - -bc7enc_bool bc7enc_compress_block(void *pBlock, const void *pPixelsRGBA, const bc7enc_compress_block_params *pComp_params) -{ - assert(g_bc7_mode_1_optimal_endpoints[255][0].m_hi != 0); - - const color_quad_u8 *pPixels = (const color_quad_u8 *)(pPixelsRGBA); - - color_cell_compressor_params params; - if (pComp_params->m_perceptual) - { - // https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.709_conversion - const float pr_weight = (.5f / (1.0f - .2126f)) * (.5f / (1.0f - .2126f)); - const float pb_weight = (.5f / (1.0f - .0722f)) * (.5f / (1.0f - .0722f)); - params.m_weights[0] = (int)(pComp_params->m_weights[0] * 4.0f); - params.m_weights[1] = (int)(pComp_params->m_weights[1] * 4.0f * pr_weight); - params.m_weights[2] = (int)(pComp_params->m_weights[2] * 4.0f * pb_weight); - params.m_weights[3] = pComp_params->m_weights[3] * 4; - } - else - memcpy(params.m_weights, pComp_params->m_weights, sizeof(params.m_weights)); - - for (uint32_t i = 0; i < 16; i++) - { - if (pPixels[i].m_c[3] < 255) - { - handle_alpha_block(pBlock, pPixels, pComp_params, ¶ms); - return BC7ENC_TRUE; - } - } - handle_opaque_block(pBlock, pPixels, pComp_params, ¶ms); - return BC7ENC_FALSE; -} - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright(c) 2020 Richard Geldreich, Jr. -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files(the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions : -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain(www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non - commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain.We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors.We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/src/rgbcx/test/bc7enc.h b/src/rgbcx/test/bc7enc.h deleted file mode 100644 index e815fc4..0000000 --- a/src/rgbcx/test/bc7enc.h +++ /dev/null @@ -1,82 +0,0 @@ -// File: bc7enc.h - Richard Geldreich, Jr. - MIT license or public domain (see end of bc7enc.c) -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define BC7ENC_BLOCK_SIZE (16) -#define BC7ENC_MAX_PARTITIONS1 (64) -#define BC7ENC_MAX_UBER_LEVEL (4) - -typedef uint8_t bc7enc_bool; -#define BC7ENC_TRUE (1) -#define BC7ENC_FALSE (0) - -typedef struct -{ - // m_max_partitions_mode may range from 0 (disables mode 1) to BC7ENC_MAX_PARTITIONS1. The higher this value, the slower the compressor, but the higher the quality. - uint32_t m_max_partitions_mode; - - // Relative RGBA or YCbCrA Weights. - uint32_t m_weights[4]; - - // m_uber_level may range from 0 to BC7ENC_MAX_UBER_LEVEL. The higher this value, the slower the compressor, but the higher the quality. - uint32_t m_uber_level; - - // If m_perceptual is true, colorspace error is computed in YCbCr space, otherwise RGB. - bc7enc_bool m_perceptual; - - // Set m_try_least_squares to false for slightly faster/lower quality compression. - bc7enc_bool m_try_least_squares; - - // When m_mode_partition_estimation_filterbank, the mode1 partition estimator skips lesser used partition patterns unless they are strongly predicted to be potentially useful. - // There's a slight loss in quality with this enabled (around .08 dB RGB PSNR or .05 dB Y PSNR), but up to a 11% gain in speed depending on the other settings. - bc7enc_bool m_mode_partition_estimation_filterbank; - - bc7enc_bool m_use_mode5_for_alpha; - bc7enc_bool m_use_mode7_for_alpha; - -} bc7enc_compress_block_params; - -inline void bc7enc_compress_block_params_init_linear_weights(bc7enc_compress_block_params *p) -{ - p->m_perceptual = BC7ENC_FALSE; - p->m_weights[0] = 1; - p->m_weights[1] = 1; - p->m_weights[2] = 1; - p->m_weights[3] = 1; -} - -inline void bc7enc_compress_block_params_init_perceptual_weights(bc7enc_compress_block_params *p) -{ - p->m_perceptual = BC7ENC_TRUE; - p->m_weights[0] = 128; - p->m_weights[1] = 64; - p->m_weights[2] = 16; - p->m_weights[3] = 32; -} - -inline void bc7enc_compress_block_params_init(bc7enc_compress_block_params *p) -{ - p->m_max_partitions_mode = BC7ENC_MAX_PARTITIONS1; - p->m_try_least_squares = BC7ENC_TRUE; - p->m_mode_partition_estimation_filterbank = BC7ENC_TRUE; - p->m_uber_level = 0; - p->m_use_mode5_for_alpha = BC7ENC_TRUE; - p->m_use_mode7_for_alpha = BC7ENC_TRUE; - bc7enc_compress_block_params_init_perceptual_weights(p); -} - -// bc7enc_compress_block_init() MUST be called before calling bc7enc_compress_block() (or you'll get artifacts). -void bc7enc_compress_block_init(); - -// Packs a single block of 16x16 RGBA pixels (R first in memory) to 128-bit BC7 block pBlock, using either mode 1 and/or 6. -// Alpha blocks will always use mode 6, and by default opaque blocks will use either modes 1 or 6. -// Returns BC7ENC_TRUE if the block had any pixels with alpha < 255, otherwise it return BC7ENC_FALSE. (This is not an error code - a block is always encoded.) -bc7enc_bool bc7enc_compress_block(void *pBlock, const void *pPixelsRGBA, const bc7enc_compress_block_params *pComp_params); - -#ifdef __cplusplus -} -#endif diff --git a/src/rgbcx/test/dds_defs.h b/src/rgbcx/test/dds_defs.h deleted file mode 100644 index 034cccf..0000000 --- a/src/rgbcx/test/dds_defs.h +++ /dev/null @@ -1,286 +0,0 @@ -// File: dds_defs.h -// DX9/10 .DDS file header definitions. -#pragma once - -#define PIXEL_FMT_FOURCC(a, b, c, d) ((a) | ((b) << 8U) | ((c) << 16U) | ((d) << 24U)) - -enum pixel_format -{ - PIXEL_FMT_INVALID = 0, - - PIXEL_FMT_DXT1 = PIXEL_FMT_FOURCC('D', 'X', 'T', '1'), - PIXEL_FMT_DXT2 = PIXEL_FMT_FOURCC('D', 'X', 'T', '2'), - PIXEL_FMT_DXT3 = PIXEL_FMT_FOURCC('D', 'X', 'T', '3'), - PIXEL_FMT_DXT4 = PIXEL_FMT_FOURCC('D', 'X', 'T', '4'), - PIXEL_FMT_DXT5 = PIXEL_FMT_FOURCC('D', 'X', 'T', '5'), - PIXEL_FMT_3DC = PIXEL_FMT_FOURCC('A', 'T', 'I', '2'), // DXN_YX - PIXEL_FMT_DXN = PIXEL_FMT_FOURCC('A', '2', 'X', 'Y'), // DXN_XY - PIXEL_FMT_DXT5A = PIXEL_FMT_FOURCC('A', 'T', 'I', '1'), // ATI1N, http://developer.amd.com/media/gpu_assets/Radeon_X1x00_Programming_Guide.pdf - - // Non-standard formats (some of these are supported by ATI's Compressonator) - PIXEL_FMT_DXT5_CCxY = PIXEL_FMT_FOURCC('C', 'C', 'x', 'Y'), - PIXEL_FMT_DXT5_xGxR = PIXEL_FMT_FOURCC('x', 'G', 'x', 'R'), - PIXEL_FMT_DXT5_xGBR = PIXEL_FMT_FOURCC('x', 'G', 'B', 'R'), - PIXEL_FMT_DXT5_AGBR = PIXEL_FMT_FOURCC('A', 'G', 'B', 'R'), - - PIXEL_FMT_DXT1A = PIXEL_FMT_FOURCC('D', 'X', '1', 'A'), - PIXEL_FMT_ETC1 = PIXEL_FMT_FOURCC('E', 'T', 'C', '1'), - - PIXEL_FMT_R8G8B8 = PIXEL_FMT_FOURCC('R', 'G', 'B', 'x'), - PIXEL_FMT_L8 = PIXEL_FMT_FOURCC('L', 'x', 'x', 'x'), - PIXEL_FMT_A8 = PIXEL_FMT_FOURCC('x', 'x', 'x', 'A'), - PIXEL_FMT_A8L8 = PIXEL_FMT_FOURCC('L', 'x', 'x', 'A'), - PIXEL_FMT_A8R8G8B8 = PIXEL_FMT_FOURCC('R', 'G', 'B', 'A') -}; - -const uint32_t cDDSMaxImageDimensions = 8192U; - -// Total size of header is sizeof(uint32)+cDDSSizeofDDSurfaceDesc2; -const uint32_t cDDSSizeofDDSurfaceDesc2 = 124; - -// "DDS " -const uint32_t cDDSFileSignature = 0x20534444; - -struct DDCOLORKEY -{ - uint32_t dwUnused0; - uint32_t dwUnused1; -}; - -struct DDPIXELFORMAT -{ - uint32_t dwSize; - uint32_t dwFlags; - uint32_t dwFourCC; - uint32_t dwRGBBitCount; // ATI compressonator will place a FOURCC code here for swizzled/cooked DXTn formats - uint32_t dwRBitMask; - uint32_t dwGBitMask; - uint32_t dwBBitMask; - uint32_t dwRGBAlphaBitMask; -}; - -struct DDSCAPS2 -{ - uint32_t dwCaps; - uint32_t dwCaps2; - uint32_t dwCaps3; - uint32_t dwCaps4; -}; - -struct DDSURFACEDESC2 -{ - uint32_t dwSize; - uint32_t dwFlags; - uint32_t dwHeight; - uint32_t dwWidth; - union - { - int32_t lPitch; - uint32_t dwLinearSize; - }; - uint32_t dwBackBufferCount; - uint32_t dwMipMapCount; - uint32_t dwAlphaBitDepth; - uint32_t dwUnused0; - uint32_t lpSurface; - DDCOLORKEY unused0; - DDCOLORKEY unused1; - DDCOLORKEY unused2; - DDCOLORKEY unused3; - DDPIXELFORMAT ddpfPixelFormat; - DDSCAPS2 ddsCaps; - uint32_t dwUnused1; -}; - -const uint32_t DDSD_CAPS = 0x00000001; -const uint32_t DDSD_HEIGHT = 0x00000002; -const uint32_t DDSD_WIDTH = 0x00000004; -const uint32_t DDSD_PITCH = 0x00000008; - -const uint32_t DDSD_BACKBUFFERCOUNT = 0x00000020; -const uint32_t DDSD_ZBUFFERBITDEPTH = 0x00000040; -const uint32_t DDSD_ALPHABITDEPTH = 0x00000080; - -const uint32_t DDSD_LPSURFACE = 0x00000800; - -const uint32_t DDSD_PIXELFORMAT = 0x00001000; -const uint32_t DDSD_CKDESTOVERLAY = 0x00002000; -const uint32_t DDSD_CKDESTBLT = 0x00004000; -const uint32_t DDSD_CKSRCOVERLAY = 0x00008000; - -const uint32_t DDSD_CKSRCBLT = 0x00010000; -const uint32_t DDSD_MIPMAPCOUNT = 0x00020000; -const uint32_t DDSD_REFRESHRATE = 0x00040000; -const uint32_t DDSD_LINEARSIZE = 0x00080000; - -const uint32_t DDSD_TEXTURESTAGE = 0x00100000; -const uint32_t DDSD_FVF = 0x00200000; -const uint32_t DDSD_SRCVBHANDLE = 0x00400000; -const uint32_t DDSD_DEPTH = 0x00800000; - -const uint32_t DDSD_ALL = 0x00fff9ee; - -const uint32_t DDPF_ALPHAPIXELS = 0x00000001; -const uint32_t DDPF_ALPHA = 0x00000002; -const uint32_t DDPF_FOURCC = 0x00000004; -const uint32_t DDPF_PALETTEINDEXED8 = 0x00000020; -const uint32_t DDPF_RGB = 0x00000040; -const uint32_t DDPF_LUMINANCE = 0x00020000; - -const uint32_t DDSCAPS_COMPLEX = 0x00000008; -const uint32_t DDSCAPS_TEXTURE = 0x00001000; -const uint32_t DDSCAPS_MIPMAP = 0x00400000; - -const uint32_t DDSCAPS2_CUBEMAP = 0x00000200; -const uint32_t DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400; -const uint32_t DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800; - -const uint32_t DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000; -const uint32_t DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000; -const uint32_t DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000; -const uint32_t DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000; - -const uint32_t DDSCAPS2_VOLUME = 0x00200000; - -typedef enum DXGI_FORMAT -{ - DXGI_FORMAT_UNKNOWN = 0, - DXGI_FORMAT_R32G32B32A32_TYPELESS = 1, - DXGI_FORMAT_R32G32B32A32_FLOAT = 2, - DXGI_FORMAT_R32G32B32A32_UINT = 3, - DXGI_FORMAT_R32G32B32A32_SINT = 4, - DXGI_FORMAT_R32G32B32_TYPELESS = 5, - DXGI_FORMAT_R32G32B32_FLOAT = 6, - DXGI_FORMAT_R32G32B32_UINT = 7, - DXGI_FORMAT_R32G32B32_SINT = 8, - DXGI_FORMAT_R16G16B16A16_TYPELESS = 9, - DXGI_FORMAT_R16G16B16A16_FLOAT = 10, - DXGI_FORMAT_R16G16B16A16_UNORM = 11, - DXGI_FORMAT_R16G16B16A16_UINT = 12, - DXGI_FORMAT_R16G16B16A16_SNORM = 13, - DXGI_FORMAT_R16G16B16A16_SINT = 14, - DXGI_FORMAT_R32G32_TYPELESS = 15, - DXGI_FORMAT_R32G32_FLOAT = 16, - DXGI_FORMAT_R32G32_UINT = 17, - DXGI_FORMAT_R32G32_SINT = 18, - DXGI_FORMAT_R32G8X24_TYPELESS = 19, - DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20, - DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21, - DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22, - DXGI_FORMAT_R10G10B10A2_TYPELESS = 23, - DXGI_FORMAT_R10G10B10A2_UNORM = 24, - DXGI_FORMAT_R10G10B10A2_UINT = 25, - DXGI_FORMAT_R11G11B10_FLOAT = 26, - DXGI_FORMAT_R8G8B8A8_TYPELESS = 27, - DXGI_FORMAT_R8G8B8A8_UNORM = 28, - DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29, - DXGI_FORMAT_R8G8B8A8_UINT = 30, - DXGI_FORMAT_R8G8B8A8_SNORM = 31, - DXGI_FORMAT_R8G8B8A8_SINT = 32, - DXGI_FORMAT_R16G16_TYPELESS = 33, - DXGI_FORMAT_R16G16_FLOAT = 34, - DXGI_FORMAT_R16G16_UNORM = 35, - DXGI_FORMAT_R16G16_UINT = 36, - DXGI_FORMAT_R16G16_SNORM = 37, - DXGI_FORMAT_R16G16_SINT = 38, - DXGI_FORMAT_R32_TYPELESS = 39, - DXGI_FORMAT_D32_FLOAT = 40, - DXGI_FORMAT_R32_FLOAT = 41, - DXGI_FORMAT_R32_UINT = 42, - DXGI_FORMAT_R32_SINT = 43, - DXGI_FORMAT_R24G8_TYPELESS = 44, - DXGI_FORMAT_D24_UNORM_S8_UINT = 45, - DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46, - DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47, - DXGI_FORMAT_R8G8_TYPELESS = 48, - DXGI_FORMAT_R8G8_UNORM = 49, - DXGI_FORMAT_R8G8_UINT = 50, - DXGI_FORMAT_R8G8_SNORM = 51, - DXGI_FORMAT_R8G8_SINT = 52, - DXGI_FORMAT_R16_TYPELESS = 53, - DXGI_FORMAT_R16_FLOAT = 54, - DXGI_FORMAT_D16_UNORM = 55, - DXGI_FORMAT_R16_UNORM = 56, - DXGI_FORMAT_R16_UINT = 57, - DXGI_FORMAT_R16_SNORM = 58, - DXGI_FORMAT_R16_SINT = 59, - DXGI_FORMAT_R8_TYPELESS = 60, - DXGI_FORMAT_R8_UNORM = 61, - DXGI_FORMAT_R8_UINT = 62, - DXGI_FORMAT_R8_SNORM = 63, - DXGI_FORMAT_R8_SINT = 64, - DXGI_FORMAT_A8_UNORM = 65, - DXGI_FORMAT_R1_UNORM = 66, - DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67, - DXGI_FORMAT_R8G8_B8G8_UNORM = 68, - DXGI_FORMAT_G8R8_G8B8_UNORM = 69, - DXGI_FORMAT_BC1_TYPELESS = 70, - DXGI_FORMAT_BC1_UNORM = 71, - DXGI_FORMAT_BC1_UNORM_SRGB = 72, - DXGI_FORMAT_BC2_TYPELESS = 73, - DXGI_FORMAT_BC2_UNORM = 74, - DXGI_FORMAT_BC2_UNORM_SRGB = 75, - DXGI_FORMAT_BC3_TYPELESS = 76, - DXGI_FORMAT_BC3_UNORM = 77, - DXGI_FORMAT_BC3_UNORM_SRGB = 78, - DXGI_FORMAT_BC4_TYPELESS = 79, - DXGI_FORMAT_BC4_UNORM = 80, - DXGI_FORMAT_BC4_SNORM = 81, - DXGI_FORMAT_BC5_TYPELESS = 82, - DXGI_FORMAT_BC5_UNORM = 83, - DXGI_FORMAT_BC5_SNORM = 84, - DXGI_FORMAT_B5G6R5_UNORM = 85, - DXGI_FORMAT_B5G5R5A1_UNORM = 86, - DXGI_FORMAT_B8G8R8A8_UNORM = 87, - DXGI_FORMAT_B8G8R8X8_UNORM = 88, - DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89, - DXGI_FORMAT_B8G8R8A8_TYPELESS = 90, - DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91, - DXGI_FORMAT_B8G8R8X8_TYPELESS = 92, - DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93, - DXGI_FORMAT_BC6H_TYPELESS = 94, - DXGI_FORMAT_BC6H_UF16 = 95, - DXGI_FORMAT_BC6H_SF16 = 96, - DXGI_FORMAT_BC7_TYPELESS = 97, - DXGI_FORMAT_BC7_UNORM = 98, - DXGI_FORMAT_BC7_UNORM_SRGB = 99, - DXGI_FORMAT_AYUV = 100, - DXGI_FORMAT_Y410 = 101, - DXGI_FORMAT_Y416 = 102, - DXGI_FORMAT_NV12 = 103, - DXGI_FORMAT_P010 = 104, - DXGI_FORMAT_P016 = 105, - DXGI_FORMAT_420_OPAQUE = 106, - DXGI_FORMAT_YUY2 = 107, - DXGI_FORMAT_Y210 = 108, - DXGI_FORMAT_Y216 = 109, - DXGI_FORMAT_NV11 = 110, - DXGI_FORMAT_AI44 = 111, - DXGI_FORMAT_IA44 = 112, - DXGI_FORMAT_P8 = 113, - DXGI_FORMAT_A8P8 = 114, - DXGI_FORMAT_B4G4R4A4_UNORM = 115, - DXGI_FORMAT_P208 = 130, - DXGI_FORMAT_V208 = 131, - DXGI_FORMAT_V408 = 132, - DXGI_FORMAT_FORCE_UINT = 0xffffffff -} DXGI_FORMAT; - -enum D3D10_RESOURCE_DIMENSION -{ - D3D10_RESOURCE_DIMENSION_UNKNOWN = 0, - D3D10_RESOURCE_DIMENSION_BUFFER = 1, - D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2, - D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3, - D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4 -}; - -struct DDS_HEADER_DXT10 -{ - DXGI_FORMAT dxgiFormat; - D3D10_RESOURCE_DIMENSION resourceDimension; - uint32_t miscFlag; - uint32_t arraySize; - uint32_t miscFlags2; -}; - diff --git a/src/rgbcx/test/lodepng.cpp b/src/rgbcx/test/lodepng.cpp deleted file mode 100644 index 6ea376f..0000000 --- a/src/rgbcx/test/lodepng.cpp +++ /dev/null @@ -1,6234 +0,0 @@ -/* -LodePNG version 20161127 - -Copyright (c) 2005-2016 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -/* -The manual and changelog are in the header file "lodepng.h" -Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. -*/ - -#pragma GCC diagnostic ignored "-Weverything" - -#include "lodepng.h" - -#include -#include -#include - -#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ -#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ -#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ -#endif /*_MSC_VER */ - -const char* LODEPNG_VERSION_STRING = "20161127"; - -/* -This source file is built up in the following large parts. The code sections -with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. --Tools for C and common code for PNG and Zlib --C Code for Zlib (huffman, deflate, ...) --C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) --The C++ wrapper around all of the above -*/ - -/*The malloc, realloc and free functions defined here with "lodepng_" in front -of the name, so that you can easily change them to others related to your -platform if needed. Everything else in the code calls these. Pass --DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out -#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and -define them in your own project's source files without needing to change -lodepng source code. Don't forget to remove "static" if you copypaste them -from here.*/ - -#ifdef LODEPNG_COMPILE_ALLOCATORS -static void* lodepng_malloc(size_t size) -{ - return malloc(size); -} - -static void* lodepng_realloc(void* ptr, size_t new_size) -{ - return realloc(ptr, new_size); -} - -static void lodepng_free(void* ptr) -{ - free(ptr); -} -#else /*LODEPNG_COMPILE_ALLOCATORS*/ -void* lodepng_malloc(size_t size); -void* lodepng_realloc(void* ptr, size_t new_size); -void lodepng_free(void* ptr); -#endif /*LODEPNG_COMPILE_ALLOCATORS*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // Tools for C, and common code for PNG and Zlib. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -Often in case of an error a value is assigned to a variable and then it breaks -out of a loop (to go to the cleanup phase of a function). This macro does that. -It makes the error handling code shorter and more readable. - -Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83); -*/ -#define CERROR_BREAK(errorvar, code)\ -{\ - errorvar = code;\ - break;\ -} - -/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ -#define ERROR_BREAK(code) CERROR_BREAK(error, code) - -/*Set error var to the error code, and return it.*/ -#define CERROR_RETURN_ERROR(errorvar, code)\ -{\ - errorvar = code;\ - return code;\ -} - -/*Try the code, if it returns error, also return the error.*/ -#define CERROR_TRY_RETURN(call)\ -{\ - unsigned error = call;\ - if(error) return error;\ -} - -/*Set error var to the error code, and return from the void function.*/ -#define CERROR_RETURN(errorvar, code)\ -{\ - errorvar = code;\ - return;\ -} - -/* -About uivector, ucvector and string: --All of them wrap dynamic arrays or text strings in a similar way. --LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. --The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. --They're not used in the interface, only internally in this file as static functions. --As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. -*/ - -#ifdef LODEPNG_COMPILE_ZLIB -/*dynamic vector of unsigned ints*/ -typedef struct uivector -{ - unsigned* data; - size_t size; /*size in number of unsigned longs*/ - size_t allocsize; /*allocated size in bytes*/ -} uivector; - -static void uivector_cleanup(void* p) -{ - ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; - lodepng_free(((uivector*)p)->data); - ((uivector*)p)->data = NULL; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_reserve(uivector* p, size_t allocsize) -{ - if (allocsize > p->allocsize) - { - size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); - void* data = lodepng_realloc(p->data, newsize); - if (data) - { - p->allocsize = newsize; - p->data = (unsigned*)data; - } - else return 0; /*error: not enough memory*/ - } - return 1; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_resize(uivector* p, size_t size) -{ - if (!uivector_reserve(p, size * sizeof(unsigned))) return 0; - p->size = size; - return 1; /*success*/ -} - -/*resize and give all new elements the value*/ -static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) -{ - size_t oldsize = p->size, i; - if (!uivector_resize(p, size)) return 0; - for (i = oldsize; i < size; ++i) p->data[i] = value; - return 1; -} - -static void uivector_init(uivector* p) -{ - p->data = NULL; - p->size = p->allocsize = 0; -} - -#ifdef LODEPNG_COMPILE_ENCODER -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned uivector_push_back(uivector* p, unsigned c) -{ - if (!uivector_resize(p, p->size + 1)) return 0; - p->data[p->size - 1] = c; - return 1; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_ZLIB*/ - -/* /////////////////////////////////////////////////////////////////////////// */ - -/*dynamic vector of unsigned chars*/ -typedef struct ucvector -{ - unsigned char* data; - size_t size; /*used size*/ - size_t allocsize; /*allocated size*/ -} ucvector; - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned ucvector_reserve(ucvector* p, size_t allocsize) -{ - if (allocsize > p->allocsize) - { - size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); - void* data = lodepng_realloc(p->data, newsize); - if (data) - { - p->allocsize = newsize; - p->data = (unsigned char*)data; - } - else return 0; /*error: not enough memory*/ - } - return 1; -} - -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned ucvector_resize(ucvector* p, size_t size) -{ - if (!ucvector_reserve(p, size * sizeof(unsigned char))) return 0; - p->size = size; - return 1; /*success*/ -} - -#ifdef LODEPNG_COMPILE_PNG - -static void ucvector_cleanup(void* p) -{ - ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; - lodepng_free(((ucvector*)p)->data); - ((ucvector*)p)->data = NULL; -} - -static void ucvector_init(ucvector* p) -{ - p->data = NULL; - p->size = p->allocsize = 0; -} -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ZLIB -/*you can both convert from vector to buffer&size and vica versa. If you use -init_buffer to take over a buffer and size, it is not needed to use cleanup*/ -static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) -{ - p->data = buffer; - p->allocsize = p->size = size; -} -#endif /*LODEPNG_COMPILE_ZLIB*/ - -#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER) -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned ucvector_push_back(ucvector* p, unsigned char c) -{ - if (!ucvector_resize(p, p->size + 1)) return 0; - p->data[p->size - 1] = c; - return 1; -} -#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ - - -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_PNG -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*returns 1 if success, 0 if failure ==> nothing done*/ -static unsigned string_resize(char** out, size_t size) -{ - char* data = (char*)lodepng_realloc(*out, size + 1); - if (data) - { - data[size] = 0; /*null termination char*/ - *out = data; - } - return data != 0; -} - -/*init a {char*, size_t} pair for use as string*/ -static void string_init(char** out) -{ - *out = NULL; - string_resize(out, 0); -} - -/*free the above pair again*/ -static void string_cleanup(char** out) -{ - lodepng_free(*out); - *out = NULL; -} - -static void string_set(char** out, const char* in) -{ - size_t insize = strlen(in), i; - if (string_resize(out, insize)) - { - for (i = 0; i != insize; ++i) - { - (*out)[i] = in[i]; - } - } -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -/* ////////////////////////////////////////////////////////////////////////// */ - -unsigned lodepng_read32bitInt(const unsigned char* buffer) -{ - return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); -} - -#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) -/*buffer must have at least 4 allocated bytes available*/ -static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) -{ - buffer[0] = (unsigned char)((value >> 24) & 0xff); - buffer[1] = (unsigned char)((value >> 16) & 0xff); - buffer[2] = (unsigned char)((value >> 8) & 0xff); - buffer[3] = (unsigned char)((value) & 0xff); -} -#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ - -#ifdef LODEPNG_COMPILE_ENCODER -static void lodepng_add32bitInt(ucvector* buffer, unsigned value) -{ - ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/ - lodepng_set32bitInt(&buffer->data[buffer->size - 4], value); -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / File IO / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_DISK - -/* returns negative value on error. This should be pure C compatible, so no fstat. */ -static long lodepng_filesize(const char* filename) -{ - FILE* file; - long size; - file = fopen(filename, "rb"); - if (!file) return -1; - - if (fseek(file, 0, SEEK_END) != 0) - { - fclose(file); - return -1; - } - - size = ftell(file); - /* It may give LONG_MAX as directory size, this is invalid for us. */ - if (size == LONG_MAX) size = -1; - - fclose(file); - return size; -} - -/* load file into buffer that already has the correct allocated size. Returns error code.*/ -static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) -{ - FILE* file; - size_t readsize; - file = fopen(filename, "rb"); - if (!file) return 78; - - readsize = fread(out, 1, size, file); - fclose(file); - - if (readsize != size) return 78; - return 0; -} - -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) -{ - long size = lodepng_filesize(filename); - if (size < 0) return 78; - *outsize = (size_t)size; - - *out = (unsigned char*)lodepng_malloc((size_t)size); - if (!(*out) && size > 0) return 83; /*the above malloc failed*/ - - return lodepng_buffer_file(*out, (size_t)size, filename); -} - -/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ -unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) -{ - FILE* file; - file = fopen(filename, "wb"); - if (!file) return 79; - fwrite((char*)buffer, 1, buffersize, file); - fclose(file); - return 0; -} - -#endif /*LODEPNG_COMPILE_DISK*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of common code and tools. Begin of Zlib related code. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_ENCODER -/*TODO: this ignores potential out of memory errors*/ -#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\ -{\ - /*add a new byte at the end*/\ - if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\ - /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\ - (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\ - ++(*bitpointer);\ -} - -static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) -{ - size_t i; - for (i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); -} - -static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) -{ - size_t i; - for (i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1) - -static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) -{ - unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream)); - ++(*bitpointer); - return result; -} - -static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) -{ - unsigned result = 0, i; - for (i = 0; i != nbits; ++i) - { - result += ((unsigned)READBIT(*bitpointer, bitstream)) << i; - ++(*bitpointer); - } - return result; -} -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflate - Huffman / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#define FIRST_LENGTH_CODE_INDEX 257 -#define LAST_LENGTH_CODE_INDEX 285 -/*256 literals, the end code, some length codes, and 2 unused codes*/ -#define NUM_DEFLATE_CODE_SYMBOLS 288 -/*the distance codes have their own symbols, 30 used, 2 unused*/ -#define NUM_DISTANCE_SYMBOLS 32 -/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ -#define NUM_CODE_LENGTH_CODES 19 - -/*the base lengths represented by codes 257-285*/ -static const unsigned LENGTHBASE[29] -= { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, - 67, 83, 99, 115, 131, 163, 195, 227, 258 }; - -/*the extra bits used by codes 257-285 (added to base length)*/ -static const unsigned LENGTHEXTRA[29] -= { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 5, 5, 5, 5, 0 }; - -/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ -static const unsigned DISTANCEBASE[30] -= { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, - 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; - -/*the extra bits of backwards distances (added to base)*/ -static const unsigned DISTANCEEXTRA[30] -= { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, - 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; - -/*the order in which "code length alphabet code lengths" are stored, out of this -the huffman tree of the dynamic huffman tree lengths is generated*/ -static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] -= { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - -/* ////////////////////////////////////////////////////////////////////////// */ - -/* -Huffman tree struct, containing multiple representations of the tree -*/ -typedef struct HuffmanTree -{ - unsigned* tree2d; - unsigned* tree1d; - unsigned* lengths; /*the lengths of the codes of the 1d-tree*/ - unsigned maxbitlen; /*maximum number of bits a single code can get*/ - unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ -} HuffmanTree; - -/*function used for debug purposes to draw the tree in ascii art with C++*/ -/* -static void HuffmanTree_draw(HuffmanTree* tree) -{ - std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; - for(size_t i = 0; i != tree->tree1d.size; ++i) - { - if(tree->lengths.data[i]) - std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; - } - std::cout << std::endl; -}*/ - -static void HuffmanTree_init(HuffmanTree* tree) -{ - tree->tree2d = 0; - tree->tree1d = 0; - tree->lengths = 0; -} - -static void HuffmanTree_cleanup(HuffmanTree* tree) -{ - lodepng_free(tree->tree2d); - lodepng_free(tree->tree1d); - lodepng_free(tree->lengths); -} - -/*the tree representation used by the decoder. return value is error*/ -static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) -{ - unsigned nodefilled = 0; /*up to which node it is filled*/ - unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ - unsigned n, i; - - tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned)); - if (!tree->tree2d) return 83; /*alloc fail*/ - - /* - convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means - uninited, a value >= numcodes is an address to another bit, a value < numcodes - is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as - many columns as codes - 1. - A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. - Here, the internal nodes are stored (what their 0 and 1 option point to). - There is only memory for such good tree currently, if there are more nodes - (due to too long length codes), error 55 will happen - */ - for (n = 0; n < tree->numcodes * 2; ++n) - { - tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ - } - - for (n = 0; n < tree->numcodes; ++n) /*the codes*/ - { - for (i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/ - { - unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1); - /*oversubscribed, see comment in lodepng_error_text*/ - if (treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55; - if (tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/ - { - if (i + 1 == tree->lengths[n]) /*last bit*/ - { - tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/ - treepos = 0; - } - else - { - /*put address of the next step in here, first that address has to be found of course - (it's just nodefilled + 1)...*/ - ++nodefilled; - /*addresses encoded with numcodes added to it*/ - tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes; - treepos = nodefilled; - } - } - else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes; - } - } - - for (n = 0; n < tree->numcodes * 2; ++n) - { - if (tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/ - } - - return 0; -} - -/* -Second step for the ...makeFromLengths and ...makeFromFrequencies functions. -numcodes, lengths and maxbitlen must already be filled in correctly. return -value is error. -*/ -static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) -{ - uivector blcount; - uivector nextcode; - unsigned error = 0; - unsigned bits, n; - - uivector_init(&blcount); - uivector_init(&nextcode); - - tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); - if (!tree->tree1d) error = 83; /*alloc fail*/ - - if (!uivector_resizev(&blcount, tree->maxbitlen + 1, 0) - || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) - error = 83; /*alloc fail*/ - - if (!error) - { - /*step 1: count number of instances of each code length*/ - for (bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]]; - /*step 2: generate the nextcode values*/ - for (bits = 1; bits <= tree->maxbitlen; ++bits) - { - nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; - } - /*step 3: generate all the codes*/ - for (n = 0; n != tree->numcodes; ++n) - { - if (tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++; - } - } - - uivector_cleanup(&blcount); - uivector_cleanup(&nextcode); - - if (!error) return HuffmanTree_make2DTree(tree); - else return error; -} - -/* -given the code lengths (as stored in the PNG file), generate the tree as defined -by Deflate. maxbitlen is the maximum bits that a code in the tree can have. -return value is error. -*/ -static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, - size_t numcodes, unsigned maxbitlen) -{ - unsigned i; - tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); - if (!tree->lengths) return 83; /*alloc fail*/ - for (i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - tree->maxbitlen = maxbitlen; - return HuffmanTree_makeFromLengths2(tree); -} - -#ifdef LODEPNG_COMPILE_ENCODER - -/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", -Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ - -/*chain node for boundary package merge*/ -typedef struct BPMNode -{ - int weight; /*the sum of all Weights in this chain*/ - unsigned index; /*index of this leaf node (called "count" in the paper)*/ - struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ - int in_use; -} BPMNode; - -/*lists of chains*/ -typedef struct BPMLists -{ - /*memory pool*/ - unsigned memsize; - BPMNode* memory; - unsigned numfree; - unsigned nextfree; - BPMNode** freelist; - /*two heads of lookahead chains per list*/ - unsigned listsize; - BPMNode** chains0; - BPMNode** chains1; -} BPMLists; - -/*creates a new chain node with the given parameters, from the memory in the lists */ -static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) -{ - unsigned i; - BPMNode* result; - - /*memory full, so garbage collect*/ - if (lists->nextfree >= lists->numfree) - { - /*mark only those that are in use*/ - for (i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; - for (i = 0; i != lists->listsize; ++i) - { - BPMNode* node; - for (node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; - for (node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; - } - /*collect those that are free*/ - lists->numfree = 0; - for (i = 0; i != lists->memsize; ++i) - { - if (!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; - } - lists->nextfree = 0; - } - - result = lists->freelist[lists->nextfree++]; - result->weight = weight; - result->index = index; - result->tail = tail; - return result; -} - -/*sort the leaves with stable mergesort*/ -static void bpmnode_sort(BPMNode* leaves, size_t num) -{ - BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); - size_t width, counter = 0; - for (width = 1; width < num; width *= 2) - { - BPMNode* a = (counter & 1) ? mem : leaves; - BPMNode* b = (counter & 1) ? leaves : mem; - size_t p; - for (p = 0; p < num; p += 2 * width) - { - size_t q = (p + width > num) ? num : (p + width); - size_t r = (p + 2 * width > num) ? num : (p + 2 * width); - size_t i = p, j = q, k; - for (k = p; k < r; k++) - { - if (i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; - else b[k] = a[j++]; - } - } - counter++; - } - if (counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num); - lodepng_free(mem); -} - -/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ -static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) -{ - unsigned lastindex = lists->chains1[c]->index; - - if (c == 0) - { - if (lastindex >= numpresent) return; - lists->chains0[c] = lists->chains1[c]; - lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); - } - else - { - /*sum of the Weights of the head nodes of the previous lookahead chains.*/ - int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; - lists->chains0[c] = lists->chains1[c]; - if (lastindex < numpresent && sum > leaves[lastindex].weight) - { - lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); - return; - } - lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); - /*in the end we are only interested in the chain of the last list, so no - need to recurse if we're at the last one (this gives measurable speedup)*/ - if (num + 1 < (int)(2 * numpresent - 2)) - { - boundaryPM(lists, leaves, numpresent, c - 1, num); - boundaryPM(lists, leaves, numpresent, c - 1, num); - } - } -} - -unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, - size_t numcodes, unsigned maxbitlen) -{ - unsigned error = 0; - unsigned i; - size_t numpresent = 0; /*number of symbols with non-zero frequency*/ - BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ - - if (numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ - if ((1u << maxbitlen) < numcodes) return 80; /*error: represent all symbols*/ - - leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); - if (!leaves) return 83; /*alloc fail*/ - - for (i = 0; i != numcodes; ++i) - { - if (frequencies[i] > 0) - { - leaves[numpresent].weight = (int)frequencies[i]; - leaves[numpresent].index = i; - ++numpresent; - } - } - - for (i = 0; i != numcodes; ++i) lengths[i] = 0; - - /*ensure at least two present symbols. There should be at least one symbol - according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To - make these work as well ensure there are at least two symbols. The - Package-Merge code below also doesn't work correctly if there's only one - symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/ - if (numpresent == 0) - { - lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ - } - else if (numpresent == 1) - { - lengths[leaves[0].index] = 1; - lengths[leaves[0].index == 0 ? 1 : 0] = 1; - } - else - { - BPMLists lists; - BPMNode* node; - - bpmnode_sort(leaves, numpresent); - - lists.listsize = maxbitlen; - lists.memsize = 2 * maxbitlen * (maxbitlen + 1); - lists.nextfree = 0; - lists.numfree = lists.memsize; - lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); - lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); - lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); - lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); - if (!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ - - if (!error) - { - for (i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; - - bpmnode_create(&lists, leaves[0].weight, 1, 0); - bpmnode_create(&lists, leaves[1].weight, 2, 0); - - for (i = 0; i != lists.listsize; ++i) - { - lists.chains0[i] = &lists.memory[0]; - lists.chains1[i] = &lists.memory[1]; - } - - /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ - for (i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); - - for (node = lists.chains1[maxbitlen - 1]; node; node = node->tail) - { - for (i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; - } - } - - lodepng_free(lists.memory); - lodepng_free(lists.freelist); - lodepng_free(lists.chains0); - lodepng_free(lists.chains1); - } - - lodepng_free(leaves); - return error; -} - -/*Create the Huffman tree given the symbol frequencies*/ -static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, - size_t mincodes, size_t numcodes, unsigned maxbitlen) -{ - unsigned error = 0; - while (!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ - tree->maxbitlen = maxbitlen; - tree->numcodes = (unsigned)numcodes; /*number of symbols*/ - tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned)); - if (!tree->lengths) return 83; /*alloc fail*/ - /*initialize all lengths to 0*/ - memset(tree->lengths, 0, numcodes * sizeof(unsigned)); - - error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); - if (!error) error = HuffmanTree_makeFromLengths2(tree); - return error; -} - -static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) -{ - return tree->tree1d[index]; -} - -static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) -{ - return tree->lengths[index]; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ -static unsigned generateFixedLitLenTree(HuffmanTree* tree) -{ - unsigned i, error = 0; - unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); - if (!bitlen) return 83; /*alloc fail*/ - - /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ - for (i = 0; i <= 143; ++i) bitlen[i] = 8; - for (i = 144; i <= 255; ++i) bitlen[i] = 9; - for (i = 256; i <= 279; ++i) bitlen[i] = 7; - for (i = 280; i <= 287; ++i) bitlen[i] = 8; - - error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); - - lodepng_free(bitlen); - return error; -} - -/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ -static unsigned generateFixedDistanceTree(HuffmanTree* tree) -{ - unsigned i, error = 0; - unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); - if (!bitlen) return 83; /*alloc fail*/ - - /*there are 32 distance codes, but 30-31 are unused*/ - for (i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; - error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); - - lodepng_free(bitlen); - return error; -} - -#ifdef LODEPNG_COMPILE_DECODER - -/* -returns the code, or (unsigned)(-1) if error happened -inbitlength is the length of the complete buffer, in bits (so its byte length times 8) -*/ -static unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp, - const HuffmanTree* codetree, size_t inbitlength) -{ - unsigned treepos = 0, ct; - for (;;) - { - if (*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/ - /* - decode the symbol from the tree. The "readBitFromStream" code is inlined in - the expression below because this is the biggest bottleneck while decoding - */ - ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)]; - ++(*bp); - if (ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/ - else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/ - - if (treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/ - } -} -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Inflator (Decompressor) / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ -static void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) -{ - /*TODO: check for out of memory errors*/ - generateFixedLitLenTree(tree_ll); - generateFixedDistanceTree(tree_d); -} - -/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ -static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, - const unsigned char* in, size_t* bp, size_t inlength) -{ - /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ - unsigned error = 0; - unsigned n, HLIT, HDIST, HCLEN, i; - size_t inbitlength = inlength * 8; - - /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ - unsigned* bitlen_ll = 0; /*lit,len code lengths*/ - unsigned* bitlen_d = 0; /*dist code lengths*/ - /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ - unsigned* bitlen_cl = 0; - HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ - - if ((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/ - - /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ - HLIT = readBitsFromStream(bp, in, 5) + 257; - /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ - HDIST = readBitsFromStream(bp, in, 5) + 1; - /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ - HCLEN = readBitsFromStream(bp, in, 4) + 4; - - if ((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/ - - HuffmanTree_init(&tree_cl); - - while (!error) - { - /*read the code length codes out of 3 * (amount of code length codes) bits*/ - - bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); - if (!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/); - - for (i = 0; i != NUM_CODE_LENGTH_CODES; ++i) - { - if (i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3); - else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/ - } - - error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); - if (error) break; - - /*now we can use this tree to read the lengths for the tree that this function will return*/ - bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); - bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); - if (!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); - for (i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0; - for (i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0; - - /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ - i = 0; - while (i < HLIT + HDIST) - { - unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength); - if (code <= 15) /*a length code*/ - { - if (i < HLIT) bitlen_ll[i] = code; - else bitlen_d[i - HLIT] = code; - ++i; - } - else if (code == 16) /*repeat previous*/ - { - unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ - unsigned value; /*set value to the previous code*/ - - if (i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ - - if ((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ - replength += readBitsFromStream(bp, in, 2); - - if (i < HLIT + 1) value = bitlen_ll[i - 1]; - else value = bitlen_d[i - HLIT - 1]; - /*repeat this value in the next lengths*/ - for (n = 0; n < replength; ++n) - { - if (i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ - if (i < HLIT) bitlen_ll[i] = value; - else bitlen_d[i - HLIT] = value; - ++i; - } - } - else if (code == 17) /*repeat "0" 3-10 times*/ - { - unsigned replength = 3; /*read in the bits that indicate repeat length*/ - if ((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ - replength += readBitsFromStream(bp, in, 3); - - /*repeat this value in the next lengths*/ - for (n = 0; n < replength; ++n) - { - if (i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ - - if (i < HLIT) bitlen_ll[i] = 0; - else bitlen_d[i - HLIT] = 0; - ++i; - } - } - else if (code == 18) /*repeat "0" 11-138 times*/ - { - unsigned replength = 11; /*read in the bits that indicate repeat length*/ - if ((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ - replength += readBitsFromStream(bp, in, 7); - - /*repeat this value in the next lengths*/ - for (n = 0; n < replength; ++n) - { - if (i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ - - if (i < HLIT) bitlen_ll[i] = 0; - else bitlen_d[i - HLIT] = 0; - ++i; - } - } - else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ - { - if (code == (unsigned)(-1)) - { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - error = (*bp) > inbitlength ? 10 : 11; - } - else error = 16; /*unexisting code, this can never happen*/ - break; - } - } - if (error) break; - - if (bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ - - /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ - error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); - if (error) break; - error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); - - break; /*end of error-while*/ - } - - lodepng_free(bitlen_cl); - lodepng_free(bitlen_ll); - lodepng_free(bitlen_d); - HuffmanTree_cleanup(&tree_cl); - - return error; -} - -/*inflate a block with dynamic of fixed Huffman tree*/ -static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp, - size_t* pos, size_t inlength, unsigned btype) -{ - unsigned error = 0; - HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ - HuffmanTree tree_d; /*the huffman tree for distance codes*/ - size_t inbitlength = inlength * 8; - - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - - if (btype == 1) getTreeInflateFixed(&tree_ll, &tree_d); - else if (btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength); - - while (!error) /*decode all symbols until end reached, breaks at end code*/ - { - /*code_ll is literal, length or end code*/ - unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength); - if (code_ll <= 255) /*literal symbol*/ - { - /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/ - if (!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/); - out->data[*pos] = (unsigned char)code_ll; - ++(*pos); - } - else if (code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ - { - unsigned code_d, distance; - unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ - size_t start, forward, backward, length; - - /*part 1: get length base*/ - length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; - - /*part 2: get extra bits and add the value of that to length*/ - numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; - if ((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ - length += readBitsFromStream(bp, in, numextrabits_l); - - /*part 3: get distance code*/ - code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength); - if (code_d > 29) - { - if (code_ll == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ - { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - error = (*bp) > inlength * 8 ? 10 : 11; - } - else error = 18; /*error: invalid distance code (30-31 are never used)*/ - break; - } - distance = DISTANCEBASE[code_d]; - - /*part 4: get extra bits from distance*/ - numextrabits_d = DISTANCEEXTRA[code_d]; - if ((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ - distance += readBitsFromStream(bp, in, numextrabits_d); - - /*part 5: fill in all the out[n] values based on the length and dist*/ - start = (*pos); - if (distance > start) ERROR_BREAK(52); /*too long backward distance*/ - backward = start - distance; - - if (!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/); - if (distance < length) { - for (forward = 0; forward < length; ++forward) - { - out->data[(*pos)++] = out->data[backward++]; - } - } - else { - memcpy(out->data + *pos, out->data + backward, length); - *pos += length; - } - } - else if (code_ll == 256) - { - break; /*end code, break the loop*/ - } - else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ - { - /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol - (10=no endcode, 11=wrong jump outside of tree)*/ - error = ((*bp) > inlength * 8) ? 10 : 11; - break; - } - } - - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - - return error; -} - -static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) -{ - size_t p; - unsigned LEN, NLEN, n, error = 0; - - /*go to first boundary of byte*/ - while (((*bp) & 0x7) != 0) ++(*bp); - p = (*bp) / 8; /*byte position*/ - - /*read LEN (2 bytes) and NLEN (2 bytes)*/ - if (p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/ - LEN = in[p] + 256u * in[p + 1]; p += 2; - NLEN = in[p] + 256u * in[p + 1]; p += 2; - - /*check if 16-bit NLEN is really the one's complement of LEN*/ - if (LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/ - - if (!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/ - - /*read the literal data: LEN bytes are now stored in the out buffer*/ - if (p + LEN > inlength) return 23; /*error: reading outside of in buffer*/ - for (n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++]; - - (*bp) = p * 8; - - return error; -} - -static unsigned lodepng_inflatev(ucvector* out, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) -{ - /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/ - size_t bp = 0; - unsigned BFINAL = 0; - size_t pos = 0; /*byte position in the out buffer*/ - unsigned error = 0; - - (void)settings; - - while (!BFINAL) - { - unsigned BTYPE; - if (bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/ - BFINAL = readBitFromStream(&bp, in); - BTYPE = 1u * readBitFromStream(&bp, in); - BTYPE += 2u * readBitFromStream(&bp, in); - - if (BTYPE == 3) return 20; /*error: invalid BTYPE*/ - else if (BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/ - else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/ - - if (error) return error; - } - - return error; -} - -unsigned lodepng_inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) -{ - unsigned error; - ucvector v; - ucvector_init_buffer(&v, *out, *outsize); - error = lodepng_inflatev(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -static unsigned inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings) -{ - if (settings->custom_inflate) - { - return settings->custom_inflate(out, outsize, in, insize, settings); - } - else - { - return lodepng_inflate(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Deflator (Compressor) / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; - -/*bitlen is the size in bits of the code*/ -static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) -{ - addBitsToStreamReversed(bp, compressed, code, bitlen); -} - -/*search the index in the array, that has the largest value smaller than or equal to the given value, -given array must be sorted (if no value is smaller, it returns the size of the given array)*/ -static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) -{ - /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ - size_t left = 1; - size_t right = array_size - 1; - - while (left <= right) { - size_t mid = (left + right) >> 1; - if (array[mid] >= value) right = mid - 1; - else left = mid + 1; - } - if (left >= array_size || array[left] > value) left--; - return left; -} - -static void addLengthDistance(uivector* values, size_t length, size_t distance) -{ - /*values in encoded vector are those used by deflate: - 0-255: literal bytes - 256: end - 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) - 286-287: invalid*/ - - unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); - unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); - unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); - unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); - - uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX); - uivector_push_back(values, extra_length); - uivector_push_back(values, dist_code); - uivector_push_back(values, extra_distance); -} - -/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 -bytes as input because 3 is the minimum match length for deflate*/ -static const unsigned HASH_NUM_VALUES = 65536; -static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ - -typedef struct Hash -{ - int* head; /*hash value to head circular pos - can be outdated if went around window*/ - /*circular pos to prev circular pos*/ - unsigned short* chain; - int* val; /*circular pos to hash value*/ - - /*TODO: do this not only for zeros but for any repeated byte. However for PNG - it's always going to be the zeros that dominate, so not important for PNG*/ - int* headz; /*similar to head, but for chainz*/ - unsigned short* chainz; /*those with same amount of zeros*/ - unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ -} Hash; - -static unsigned hash_init(Hash* hash, unsigned windowsize) -{ - unsigned i; - hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); - hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); - hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - - hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); - hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); - - if (!hash->head || !hash->chain || !hash->val || !hash->headz || !hash->chainz || !hash->zeros) - { - return 83; /*alloc fail*/ - } - - /*initialize hash table*/ - for (i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; - for (i = 0; i != windowsize; ++i) hash->val[i] = -1; - for (i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ - - for (i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; - for (i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ - - return 0; -} - -static void hash_cleanup(Hash* hash) -{ - lodepng_free(hash->head); - lodepng_free(hash->val); - lodepng_free(hash->chain); - - lodepng_free(hash->zeros); - lodepng_free(hash->headz); - lodepng_free(hash->chainz); -} - - - -static unsigned getHash(const unsigned char* data, size_t size, size_t pos) -{ - unsigned result = 0; - if (pos + 2 < size) - { - /*A simple shift and xor hash is used. Since the data of PNGs is dominated - by zeroes due to the filters, a better hash does not have a significant - effect on speed in traversing the chain, and causes more time spend on - calculating the hash.*/ - result ^= (unsigned)(data[pos + 0] << 0u); - result ^= (unsigned)(data[pos + 1] << 4u); - result ^= (unsigned)(data[pos + 2] << 8u); - } - else { - size_t amount, i; - if (pos >= size) return 0; - amount = size - pos; - for (i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u)); - } - return result & HASH_BIT_MASK; -} - -static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) -{ - const unsigned char* start = data + pos; - const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; - if (end > data + size) end = data + size; - data = start; - while (data != end && *data == 0) ++data; - /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ - return (unsigned)(data - start); -} - -/*wpos = pos & (windowsize - 1)*/ -static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) -{ - hash->val[wpos] = (int)hashval; - if (hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; - hash->head[hashval] = wpos; - - hash->zeros[wpos] = numzeros; - if (hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; - hash->headz[numzeros] = wpos; -} - -/* -LZ77-encode the data. Return value is error code. The input are raw bytes, the output -is in the form of unsigned integers with codes representing for example literal bytes, or -length/distance pairs. -It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a -sliding window (of windowsize) is used, and all past bytes in that window can be used as -the "dictionary". A brute force search through all possible distances would be slow, and -this hash technique is one out of several ways to speed this up. -*/ -static unsigned encodeLZ77(uivector* out, Hash* hash, - const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, - unsigned minmatch, unsigned nicematch, unsigned lazymatching) -{ - size_t pos; - unsigned i, error = 0; - /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ - unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8; - unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; - - unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ - unsigned numzeros = 0; - - unsigned offset; /*the offset represents the distance in LZ77 terminology*/ - unsigned length; - unsigned lazy = 0; - unsigned lazylength = 0, lazyoffset = 0; - unsigned hashval; - unsigned current_offset, current_length; - unsigned prev_offset; - const unsigned char *lastptr, *foreptr, *backptr; - unsigned hashpos; - - if (windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ - if ((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ - - if (nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; - - for (pos = inpos; pos < insize; ++pos) - { - size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ - unsigned chainlength = 0; - - hashval = getHash(in, insize, pos); - - if (usezeros && hashval == 0) - { - if (numzeros == 0) numzeros = countZeros(in, insize, pos); - else if (pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; - } - else - { - numzeros = 0; - } - - updateHashChain(hash, wpos, hashval, numzeros); - - /*the length and offset found for the current position*/ - length = 0; - offset = 0; - - hashpos = hash->chain[wpos]; - - lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; - - /*search for the longest string*/ - prev_offset = 0; - for (;;) - { - if (chainlength++ >= maxchainlength) break; - current_offset = hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize; - - if (current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ - prev_offset = current_offset; - if (current_offset > 0) - { - /*test the next characters*/ - foreptr = &in[pos]; - backptr = &in[pos - current_offset]; - - /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ - if (numzeros >= 3) - { - unsigned skip = hash->zeros[hashpos]; - if (skip > numzeros) skip = numzeros; - backptr += skip; - foreptr += skip; - } - - while (foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ - { - ++backptr; - ++foreptr; - } - current_length = (unsigned)(foreptr - &in[pos]); - - if (current_length > length) - { - length = current_length; /*the longest length*/ - offset = current_offset; /*the offset that is related to this longest length*/ - /*jump out once a length of max length is found (speed gain). This also jumps - out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ - if (current_length >= nicematch) break; - } - } - - if (hashpos == hash->chain[hashpos]) break; - - if (numzeros >= 3 && length > numzeros) - { - hashpos = hash->chainz[hashpos]; - if (hash->zeros[hashpos] != numzeros) break; - } - else - { - hashpos = hash->chain[hashpos]; - /*outdated hash value, happens if particular value was not encountered in whole last window*/ - if (hash->val[hashpos] != (int)hashval) break; - } - } - - if (lazymatching) - { - if (!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) - { - lazy = 1; - lazylength = length; - lazyoffset = offset; - continue; /*try the next byte*/ - } - if (lazy) - { - lazy = 0; - if (pos == 0) ERROR_BREAK(81); - if (length > lazylength + 1) - { - /*push the previous character as literal*/ - if (!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); - } - else - { - length = lazylength; - offset = lazyoffset; - hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ - hash->headz[numzeros] = -1; /*idem*/ - --pos; - } - } - } - if (length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); - - /*encode it as length/distance pair or literal value*/ - if (length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ - { - if (!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); - } - else if (length < minmatch || (length == 3 && offset > 4096)) - { - /*compensate for the fact that longer offsets have more extra bits, a - length of only 3 may be not worth it then*/ - if (!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); - } - else - { - addLengthDistance(out, length, offset); - for (i = 1; i < length; ++i) - { - ++pos; - wpos = pos & (windowsize - 1); - hashval = getHash(in, insize, pos); - if (usezeros && hashval == 0) - { - if (numzeros == 0) numzeros = countZeros(in, insize, pos); - else if (pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; - } - else - { - numzeros = 0; - } - updateHashChain(hash, wpos, hashval, numzeros); - } - } - } /*end of the loop through each character of input*/ - - return error; -} - -/* /////////////////////////////////////////////////////////////////////////// */ - -static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) -{ - /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, - 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ - - size_t i, j, numdeflateblocks = (datasize + 65534) / 65535; - unsigned datapos = 0; - for (i = 0; i != numdeflateblocks; ++i) - { - unsigned BFINAL, BTYPE, LEN, NLEN; - unsigned char firstbyte; - - BFINAL = (i == numdeflateblocks - 1); - BTYPE = 0; - - firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); - ucvector_push_back(out, firstbyte); - - LEN = 65535; - if (datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; - NLEN = 65535 - LEN; - - ucvector_push_back(out, (unsigned char)(LEN & 255)); - ucvector_push_back(out, (unsigned char)(LEN >> 8)); - ucvector_push_back(out, (unsigned char)(NLEN & 255)); - ucvector_push_back(out, (unsigned char)(NLEN >> 8)); - - /*Decompressed data*/ - for (j = 0; j < 65535 && datapos < datasize; ++j) - { - ucvector_push_back(out, data[datapos++]); - } - } - - return 0; -} - -/* -write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. -tree_ll: the tree for lit and len codes. -tree_d: the tree for distance codes. -*/ -static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded, - const HuffmanTree* tree_ll, const HuffmanTree* tree_d) -{ - size_t i = 0; - for (i = 0; i != lz77_encoded->size; ++i) - { - unsigned val = lz77_encoded->data[i]; - addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val)); - if (val > 256) /*for a length code, 3 more things have to be added*/ - { - unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; - unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; - unsigned length_extra_bits = lz77_encoded->data[++i]; - - unsigned distance_code = lz77_encoded->data[++i]; - - unsigned distance_index = distance_code; - unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; - unsigned distance_extra_bits = lz77_encoded->data[++i]; - - addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits); - addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code), - HuffmanTree_getLength(tree_d, distance_code)); - addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits); - } - } -} - -/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ -static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, - const unsigned char* data, size_t datapos, size_t dataend, - const LodePNGCompressSettings* settings, unsigned final) -{ - unsigned error = 0; - - /* - A block is compressed as follows: The PNG data is lz77 encoded, resulting in - literal bytes and length/distance pairs. This is then huffman compressed with - two huffman trees. One huffman tree is used for the lit and len values ("ll"), - another huffman tree is used for the dist values ("d"). These two trees are - stored using their code lengths, and to compress even more these code lengths - are also run-length encoded and huffman compressed. This gives a huffman tree - of code lengths "cl". The code lenghts used to describe this third tree are - the code length code lengths ("clcl"). - */ - - /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ - uivector lz77_encoded; - HuffmanTree tree_ll; /*tree for lit,len values*/ - HuffmanTree tree_d; /*tree for distance codes*/ - HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ - uivector frequencies_ll; /*frequency of lit,len codes*/ - uivector frequencies_d; /*frequency of dist codes*/ - uivector frequencies_cl; /*frequency of code length codes*/ - uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/ - uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/ - /*bitlen_cl is the code length code lengths ("clcl"). The bit lengths of codes to represent tree_cl - (these are written as is in the file, it would be crazy to compress these using yet another huffman - tree that needs to be represented by yet another set of code lengths)*/ - uivector bitlen_cl; - size_t datasize = dataend - datapos; - - /* - Due to the huffman compression of huffman tree representations ("two levels"), there are some anologies: - bitlen_lld is to tree_cl what data is to tree_ll and tree_d. - bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. - bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. - */ - - unsigned BFINAL = final; - size_t numcodes_ll, numcodes_d, i; - unsigned HLIT, HDIST, HCLEN; - - uivector_init(&lz77_encoded); - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - HuffmanTree_init(&tree_cl); - uivector_init(&frequencies_ll); - uivector_init(&frequencies_d); - uivector_init(&frequencies_cl); - uivector_init(&bitlen_lld); - uivector_init(&bitlen_lld_e); - uivector_init(&bitlen_cl); - - /*This while loop never loops due to a break at the end, it is here to - allow breaking out of it to the cleanup phase on error conditions.*/ - while (!error) - { - if (settings->use_lz77) - { - error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, - settings->minmatch, settings->nicematch, settings->lazymatching); - if (error) break; - } - else - { - if (!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); - for (i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ - } - - if (!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/); - if (!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/); - - /*Count the frequencies of lit, len and dist codes*/ - for (i = 0; i != lz77_encoded.size; ++i) - { - unsigned symbol = lz77_encoded.data[i]; - ++frequencies_ll.data[symbol]; - if (symbol > 256) - { - unsigned dist = lz77_encoded.data[i + 2]; - ++frequencies_d.data[dist]; - i += 3; - } - } - frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ - - /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ - error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15); - if (error) break; - /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ - error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15); - if (error) break; - - numcodes_ll = tree_ll.numcodes; if (numcodes_ll > 286) numcodes_ll = 286; - numcodes_d = tree_d.numcodes; if (numcodes_d > 30) numcodes_d = 30; - /*store the code lengths of both generated trees in bitlen_lld*/ - for (i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i)); - for (i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i)); - - /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), - 17 (3-10 zeroes), 18 (11-138 zeroes)*/ - for (i = 0; i != (unsigned)bitlen_lld.size; ++i) - { - unsigned j = 0; /*amount of repititions*/ - while (i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j; - - if (bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/ - { - ++j; /*include the first zero*/ - if (j <= 10) /*repeat code 17 supports max 10 zeroes*/ - { - uivector_push_back(&bitlen_lld_e, 17); - uivector_push_back(&bitlen_lld_e, j - 3); - } - else /*repeat code 18 supports max 138 zeroes*/ - { - if (j > 138) j = 138; - uivector_push_back(&bitlen_lld_e, 18); - uivector_push_back(&bitlen_lld_e, j - 11); - } - i += (j - 1); - } - else if (j >= 3) /*repeat code for value other than zero*/ - { - size_t k; - unsigned num = j / 6, rest = j % 6; - uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]); - for (k = 0; k < num; ++k) - { - uivector_push_back(&bitlen_lld_e, 16); - uivector_push_back(&bitlen_lld_e, 6 - 3); - } - if (rest >= 3) - { - uivector_push_back(&bitlen_lld_e, 16); - uivector_push_back(&bitlen_lld_e, rest - 3); - } - else j -= rest; - i += j; - } - else /*too short to benefit from repeat code*/ - { - uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]); - } - } - - /*generate tree_cl, the huffmantree of huffmantrees*/ - - if (!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/); - for (i = 0; i != bitlen_lld_e.size; ++i) - { - ++frequencies_cl.data[bitlen_lld_e.data[i]]; - /*after a repeat code come the bits that specify the number of repetitions, - those don't need to be in the frequencies_cl calculation*/ - if (bitlen_lld_e.data[i] >= 16) ++i; - } - - error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data, - frequencies_cl.size, frequencies_cl.size, 7); - if (error) break; - - if (!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/); - for (i = 0; i != tree_cl.numcodes; ++i) - { - /*lenghts of code length tree is in the order as specified by deflate*/ - bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]); - } - while (bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4) - { - /*remove zeros at the end, but minimum size must be 4*/ - if (!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/); - } - if (error) break; - - /* - Write everything into the output - - After the BFINAL and BTYPE, the dynamic block consists out of the following: - - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN - - (HCLEN+4)*3 bits code lengths of code length alphabet - - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length - alphabet, + possible repetition codes 16, 17, 18) - - HDIST + 1 code lengths of distance alphabet (encoded using the code length - alphabet, + possible repetition codes 16, 17, 18) - - compressed data - - 256 (end code) - */ - - /*Write block type*/ - addBitToStream(bp, out, BFINAL); - addBitToStream(bp, out, 0); /*first bit of BTYPE "dynamic"*/ - addBitToStream(bp, out, 1); /*second bit of BTYPE "dynamic"*/ - - /*write the HLIT, HDIST and HCLEN values*/ - HLIT = (unsigned)(numcodes_ll - 257); - HDIST = (unsigned)(numcodes_d - 1); - HCLEN = (unsigned)bitlen_cl.size - 4; - /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/ - while (!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN; - addBitsToStream(bp, out, HLIT, 5); - addBitsToStream(bp, out, HDIST, 5); - addBitsToStream(bp, out, HCLEN, 4); - - /*write the code lenghts of the code length alphabet*/ - for (i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3); - - /*write the lenghts of the lit/len AND the dist alphabet*/ - for (i = 0; i != bitlen_lld_e.size; ++i) - { - addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]), - HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i])); - /*extra bits of repeat codes*/ - if (bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2); - else if (bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3); - else if (bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7); - } - - /*write the compressed data symbols*/ - writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d); - /*error: the length of the end code 256 must be larger than 0*/ - if (HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64); - - /*write the end code*/ - addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256)); - - break; /*end of error-while*/ - } - - /*cleanup*/ - uivector_cleanup(&lz77_encoded); - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - HuffmanTree_cleanup(&tree_cl); - uivector_cleanup(&frequencies_ll); - uivector_cleanup(&frequencies_d); - uivector_cleanup(&frequencies_cl); - uivector_cleanup(&bitlen_lld_e); - uivector_cleanup(&bitlen_lld); - uivector_cleanup(&bitlen_cl); - - return error; -} - -static unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash, - const unsigned char* data, - size_t datapos, size_t dataend, - const LodePNGCompressSettings* settings, unsigned final) -{ - HuffmanTree tree_ll; /*tree for literal values and length codes*/ - HuffmanTree tree_d; /*tree for distance codes*/ - - unsigned BFINAL = final; - unsigned error = 0; - size_t i; - - HuffmanTree_init(&tree_ll); - HuffmanTree_init(&tree_d); - - generateFixedLitLenTree(&tree_ll); - generateFixedDistanceTree(&tree_d); - - addBitToStream(bp, out, BFINAL); - addBitToStream(bp, out, 1); /*first bit of BTYPE*/ - addBitToStream(bp, out, 0); /*second bit of BTYPE*/ - - if (settings->use_lz77) /*LZ77 encoded*/ - { - uivector lz77_encoded; - uivector_init(&lz77_encoded); - error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, - settings->minmatch, settings->nicematch, settings->lazymatching); - if (!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d); - uivector_cleanup(&lz77_encoded); - } - else /*no LZ77, but still will be Huffman compressed*/ - { - for (i = datapos; i < dataend; ++i) - { - addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i])); - } - } - /*add END code*/ - if (!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256)); - - /*cleanup*/ - HuffmanTree_cleanup(&tree_ll); - HuffmanTree_cleanup(&tree_d); - - return error; -} - -static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) -{ - unsigned error = 0; - size_t i, blocksize, numdeflateblocks; - size_t bp = 0; /*the bit pointer*/ - Hash hash; - - if (settings->btype > 2) return 61; - else if (settings->btype == 0) return deflateNoCompression(out, in, insize); - else if (settings->btype == 1) blocksize = insize; - else /*if(settings->btype == 2)*/ - { - /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ - blocksize = insize / 8 + 8; - if (blocksize < 65536) blocksize = 65536; - if (blocksize > 262144) blocksize = 262144; - } - - numdeflateblocks = (insize + blocksize - 1) / blocksize; - if (numdeflateblocks == 0) numdeflateblocks = 1; - - error = hash_init(&hash, settings->windowsize); - if (error) return error; - - for (i = 0; i != numdeflateblocks && !error; ++i) - { - unsigned final = (i == numdeflateblocks - 1); - size_t start = i * blocksize; - size_t end = start + blocksize; - if (end > insize) end = insize; - - if (settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final); - else if (settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final); - } - - hash_cleanup(&hash); - - return error; -} - -unsigned lodepng_deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) -{ - unsigned error; - ucvector v; - ucvector_init_buffer(&v, *out, *outsize); - error = lodepng_deflatev(&v, in, insize, settings); - *out = v.data; - *outsize = v.size; - return error; -} - -static unsigned deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings) -{ - if (settings->custom_deflate) - { - return settings->custom_deflate(out, outsize, in, insize, settings); - } - else - { - return lodepng_deflate(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Adler32 */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) -{ - unsigned s1 = adler & 0xffff; - unsigned s2 = (adler >> 16) & 0xffff; - - while (len > 0) - { - /*at least 5550 sums can be done before the sums overflow, saving a lot of module divisions*/ - unsigned amount = len > 5550 ? 5550 : len; - len -= amount; - while (amount > 0) - { - s1 += (*data++); - s2 += s1; - --amount; - } - s1 %= 65521; - s2 %= 65521; - } - - return (s2 << 16) | s1; -} - -/*Return the adler32 of the bytes data[0..len-1]*/ -static unsigned adler32(const unsigned char* data, unsigned len) -{ - return update_adler32(1L, data, len); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Zlib / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_DECODER - -unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGDecompressSettings* settings) -{ - unsigned error = 0; - unsigned CM, CINFO, FDICT; - - if (insize < 2) return 53; /*error, size of zlib data too small*/ - /*read information from zlib header*/ - if ((in[0] * 256 + in[1]) % 31 != 0) - { - /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ - return 24; - } - - CM = in[0] & 15; - CINFO = (in[0] >> 4) & 15; - /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ - FDICT = (in[1] >> 5) & 1; - /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ - - if (CM != 8 || CINFO > 7) - { - /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ - return 25; - } - if (FDICT != 0) - { - /*error: the specification of PNG says about the zlib stream: - "The additional flags shall not specify a preset dictionary."*/ - return 26; - } - - error = inflate(out, outsize, in + 2, insize - 2, settings); - if (error) return error; - - if (!settings->ignore_adler32) - { - unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); - unsigned checksum = adler32(*out, (unsigned)(*outsize)); - if (checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ - } - - return 0; /*no error*/ -} - -static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGDecompressSettings* settings) -{ - if (settings->custom_zlib) - { - return settings->custom_zlib(out, outsize, in, insize, settings); - } - else - { - return lodepng_zlib_decompress(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - -unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) -{ - /*initially, *out must be NULL and outsize 0, if you just give some random *out - that's pointing to a non allocated buffer, this'll crash*/ - ucvector outv; - size_t i; - unsigned error; - unsigned char* deflatedata = 0; - size_t deflatesize = 0; - - /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ - unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ - unsigned FLEVEL = 0; - unsigned FDICT = 0; - unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; - unsigned FCHECK = 31 - CMFFLG % 31; - CMFFLG += FCHECK; - - /*ucvector-controlled version of the output buffer, for dynamic array*/ - ucvector_init_buffer(&outv, *out, *outsize); - - ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8)); - ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255)); - - error = deflate(&deflatedata, &deflatesize, in, insize, settings); - - if (!error) - { - unsigned ADLER32 = adler32(in, (unsigned)insize); - for (i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]); - lodepng_free(deflatedata); - lodepng_add32bitInt(&outv, ADLER32); - } - - *out = outv.data; - *outsize = outv.size; - - return error; -} - -/* compress using the default or custom zlib function */ -static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) -{ - if (settings->custom_zlib) - { - return settings->custom_zlib(out, outsize, in, insize, settings); - } - else - { - return lodepng_zlib_compress(out, outsize, in, insize, settings); - } -} - -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#else /*no LODEPNG_COMPILE_ZLIB*/ - -#ifdef LODEPNG_COMPILE_DECODER -static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGDecompressSettings* settings) -{ - if (!settings->custom_zlib) return 87; /*no custom zlib function provided */ - return settings->custom_zlib(out, outsize, in, insize, settings); -} -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER -static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, - size_t insize, const LodePNGCompressSettings* settings) -{ - if (!settings->custom_zlib) return 87; /*no custom zlib function provided */ - return settings->custom_zlib(out, outsize, in, insize, settings); -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#endif /*LODEPNG_COMPILE_ZLIB*/ - -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_ENCODER - -/*this is a good tradeoff between speed and compression ratio*/ -#define DEFAULT_WINDOWSIZE 2048 - -void lodepng_compress_settings_init(LodePNGCompressSettings* settings) -{ - /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ - settings->btype = 2; - settings->use_lz77 = 1; - settings->windowsize = DEFAULT_WINDOWSIZE; - settings->minmatch = 3; - settings->nicematch = 128; - settings->lazymatching = 1; - - settings->custom_zlib = 0; - settings->custom_deflate = 0; - settings->custom_context = 0; -} - -const LodePNGCompressSettings lodepng_default_compress_settings = { 2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0 }; - - -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DECODER - -void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) -{ - settings->ignore_adler32 = 0; - - settings->custom_zlib = 0; - settings->custom_inflate = 0; - settings->custom_context = 0; -} - -const LodePNGDecompressSettings lodepng_default_decompress_settings = { 0, 0, 0, 0 }; - -#endif /*LODEPNG_COMPILE_DECODER*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // End of Zlib related code. Begin of PNG related code. // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_PNG - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / CRC32 / */ -/* ////////////////////////////////////////////////////////////////////////// */ - - -#ifndef LODEPNG_NO_COMPILE_CRC -/* CRC polynomial: 0xedb88320 */ -static unsigned lodepng_crc32_table[256] = { - 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, - 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, - 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, - 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, - 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, - 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, - 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, - 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, - 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, - 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, - 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, - 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, - 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, - 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, - 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, - 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, - 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, - 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, - 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, - 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, - 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, - 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, - 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, - 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, - 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, - 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, - 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, - 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, - 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, - 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, - 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, - 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u -}; - -/*Return the CRC of the bytes buf[0..len-1].*/ -unsigned lodepng_crc32(const unsigned char* data, size_t length) -{ - unsigned r = 0xffffffffu; - size_t i; - for (i = 0; i < length; ++i) - { - r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8); - } - return r ^ 0xffffffffu; -} -#else /* !LODEPNG_NO_COMPILE_CRC */ -unsigned lodepng_crc32(const unsigned char* data, size_t length); -#endif /* !LODEPNG_NO_COMPILE_CRC */ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Reading and writing single bits and bytes from/to stream for LodePNG / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) -{ - unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); - ++(*bitpointer); - return result; -} - -static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) -{ - unsigned result = 0; - size_t i; - for (i = 0; i < nbits; ++i) - { - result <<= 1; - result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); - } - return result; -} - -#ifdef LODEPNG_COMPILE_DECODER -static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) -{ - /*the current bit in bitstream must be 0 for this to work*/ - if (bit) - { - /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ - bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); - } - ++(*bitpointer); -} -#endif /*LODEPNG_COMPILE_DECODER*/ - -static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) -{ - /*the current bit in bitstream may be 0 or 1 for this to work*/ - if (bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7)))); - else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7))); - ++(*bitpointer); -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG chunks / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -unsigned lodepng_chunk_length(const unsigned char* chunk) -{ - return lodepng_read32bitInt(&chunk[0]); -} - -void lodepng_chunk_type(char type[5], const unsigned char* chunk) -{ - unsigned i; - for (i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; - type[4] = 0; /*null termination char*/ -} - -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) -{ - if (strlen(type) != 4) return 0; - return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); -} - -unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) -{ - return((chunk[4] & 32) != 0); -} - -unsigned char lodepng_chunk_private(const unsigned char* chunk) -{ - return((chunk[6] & 32) != 0); -} - -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) -{ - return((chunk[7] & 32) != 0); -} - -unsigned char* lodepng_chunk_data(unsigned char* chunk) -{ - return &chunk[8]; -} - -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) -{ - return &chunk[8]; -} - -unsigned lodepng_chunk_check_crc(const unsigned char* chunk) -{ - unsigned length = lodepng_chunk_length(chunk); - unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); - /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ - unsigned checksum = lodepng_crc32(&chunk[4], length + 4); - if (CRC != checksum) return 1; - else return 0; -} - -void lodepng_chunk_generate_crc(unsigned char* chunk) -{ - unsigned length = lodepng_chunk_length(chunk); - unsigned CRC = lodepng_crc32(&chunk[4], length + 4); - lodepng_set32bitInt(chunk + 8 + length, CRC); -} - -unsigned char* lodepng_chunk_next(unsigned char* chunk) -{ - unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; - return &chunk[total_chunk_length]; -} - -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk) -{ - unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; - return &chunk[total_chunk_length]; -} - -unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk) -{ - unsigned i; - unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; - unsigned char *chunk_start, *new_buffer; - size_t new_length = (*outlength) + total_chunk_length; - if (new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/ - - new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); - if (!new_buffer) return 83; /*alloc fail*/ - (*out) = new_buffer; - (*outlength) = new_length; - chunk_start = &(*out)[new_length - total_chunk_length]; - - for (i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; - - return 0; -} - -unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, - const char* type, const unsigned char* data) -{ - unsigned i; - unsigned char *chunk, *new_buffer; - size_t new_length = (*outlength) + length + 12; - if (new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/ - new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); - if (!new_buffer) return 83; /*alloc fail*/ - (*out) = new_buffer; - (*outlength) = new_length; - chunk = &(*out)[(*outlength) - length - 12]; - - /*1: length*/ - lodepng_set32bitInt(chunk, (unsigned)length); - - /*2: chunk name (4 letters)*/ - chunk[4] = (unsigned char)type[0]; - chunk[5] = (unsigned char)type[1]; - chunk[6] = (unsigned char)type[2]; - chunk[7] = (unsigned char)type[3]; - - /*3: the data*/ - for (i = 0; i != length; ++i) chunk[8 + i] = data[i]; - - /*4: CRC (of the chunkname characters and the data)*/ - lodepng_chunk_generate_crc(chunk); - - return 0; -} - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / Color types and such / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*return type is a LodePNG error code*/ -static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/ -{ - switch (colortype) - { - case 0: if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/ - case 2: if (!(bd == 8 || bd == 16)) return 37; break; /*RGB*/ - case 3: if (!(bd == 1 || bd == 2 || bd == 4 || bd == 8)) return 37; break; /*palette*/ - case 4: if (!(bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/ - case 6: if (!(bd == 8 || bd == 16)) return 37; break; /*RGBA*/ - default: return 31; - } - return 0; /*allowed color type / bits combination*/ -} - -static unsigned getNumColorChannels(LodePNGColorType colortype) -{ - switch (colortype) - { - case 0: return 1; /*grey*/ - case 2: return 3; /*RGB*/ - case 3: return 1; /*palette*/ - case 4: return 2; /*grey + alpha*/ - case 6: return 4; /*RGBA*/ - } - return 0; /*unexisting color type*/ -} - -static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) -{ - /*bits per pixel is amount of channels * bits per channel*/ - return getNumColorChannels(colortype) * bitdepth; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -void lodepng_color_mode_init(LodePNGColorMode* info) -{ - info->key_defined = 0; - info->key_r = info->key_g = info->key_b = 0; - info->colortype = LCT_RGBA; - info->bitdepth = 8; - info->palette = 0; - info->palettesize = 0; -} - -void lodepng_color_mode_cleanup(LodePNGColorMode* info) -{ - lodepng_palette_clear(info); -} - -unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) -{ - size_t i; - lodepng_color_mode_cleanup(dest); - *dest = *source; - if (source->palette) - { - dest->palette = (unsigned char*)lodepng_malloc(1024); - if (!dest->palette && source->palettesize) return 83; /*alloc fail*/ - for (i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i]; - } - return 0; -} - -static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) -{ - size_t i; - if (a->colortype != b->colortype) return 0; - if (a->bitdepth != b->bitdepth) return 0; - if (a->key_defined != b->key_defined) return 0; - if (a->key_defined) - { - if (a->key_r != b->key_r) return 0; - if (a->key_g != b->key_g) return 0; - if (a->key_b != b->key_b) return 0; - } - /*if one of the palette sizes is 0, then we consider it to be the same as the - other: it means that e.g. the palette was not given by the user and should be - considered the same as the palette inside the PNG.*/ - if (1/*a->palettesize != 0 && b->palettesize != 0*/) { - if (a->palettesize != b->palettesize) return 0; - for (i = 0; i != a->palettesize * 4; ++i) - { - if (a->palette[i] != b->palette[i]) return 0; - } - } - return 1; -} - -void lodepng_palette_clear(LodePNGColorMode* info) -{ - if (info->palette) lodepng_free(info->palette); - info->palette = 0; - info->palettesize = 0; -} - -unsigned lodepng_palette_add(LodePNGColorMode* info, - unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - unsigned char* data; - /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with - the max of 256 colors, it'll have the exact alloc size*/ - if (!info->palette) /*allocate palette if empty*/ - { - /*room for 256 colors with 4 bytes each*/ - data = (unsigned char*)lodepng_realloc(info->palette, 1024); - if (!data) return 83; /*alloc fail*/ - else info->palette = data; - } - info->palette[4 * info->palettesize + 0] = r; - info->palette[4 * info->palettesize + 1] = g; - info->palette[4 * info->palettesize + 2] = b; - info->palette[4 * info->palettesize + 3] = a; - ++info->palettesize; - return 0; -} - -unsigned lodepng_get_bpp(const LodePNGColorMode* info) -{ - /*calculate bits per pixel out of colortype and bitdepth*/ - return lodepng_get_bpp_lct(info->colortype, info->bitdepth); -} - -unsigned lodepng_get_channels(const LodePNGColorMode* info) -{ - return getNumColorChannels(info->colortype); -} - -unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) -{ - return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; -} - -unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) -{ - return (info->colortype & 4) != 0; /*4 or 6*/ -} - -unsigned lodepng_is_palette_type(const LodePNGColorMode* info) -{ - return info->colortype == LCT_PALETTE; -} - -unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) -{ - size_t i; - for (i = 0; i != info->palettesize; ++i) - { - if (info->palette[i * 4 + 3] < 255) return 1; - } - return 0; -} - -unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) -{ - return info->key_defined - || lodepng_is_alpha_type(info) - || lodepng_has_palette_alpha(info); -} - -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) -{ - /*will not overflow for any color type if roughly w * h < 268435455*/ - size_t bpp = lodepng_get_bpp(color); - size_t n = w * h; - return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; -} - -size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) -{ - /*will not overflow for any color type if roughly w * h < 268435455*/ - size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); - size_t n = w * h; - return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; -} - - -#ifdef LODEPNG_COMPILE_PNG -#ifdef LODEPNG_COMPILE_DECODER -/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer*/ -static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) -{ - /*will not overflow for any color type if roughly w * h < 268435455*/ - size_t bpp = lodepng_get_bpp(color); - size_t line = ((w / 8) * bpp) + ((w & 7) * bpp + 7) / 8; - return h * line; -} -#endif /*LODEPNG_COMPILE_DECODER*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -static void LodePNGUnknownChunks_init(LodePNGInfo* info) -{ - unsigned i; - for (i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; - for (i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; -} - -static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) -{ - unsigned i; - for (i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); -} - -static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) -{ - unsigned i; - - LodePNGUnknownChunks_cleanup(dest); - - for (i = 0; i != 3; ++i) - { - size_t j; - dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; - dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); - if (!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ - for (j = 0; j < src->unknown_chunks_size[i]; ++j) - { - dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; - } - } - - return 0; -} - -/******************************************************************************/ - -static void LodePNGText_init(LodePNGInfo* info) -{ - info->text_num = 0; - info->text_keys = NULL; - info->text_strings = NULL; -} - -static void LodePNGText_cleanup(LodePNGInfo* info) -{ - size_t i; - for (i = 0; i != info->text_num; ++i) - { - string_cleanup(&info->text_keys[i]); - string_cleanup(&info->text_strings[i]); - } - lodepng_free(info->text_keys); - lodepng_free(info->text_strings); -} - -static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) -{ - size_t i = 0; - dest->text_keys = 0; - dest->text_strings = 0; - dest->text_num = 0; - for (i = 0; i != source->text_num; ++i) - { - CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); - } - return 0; -} - -void lodepng_clear_text(LodePNGInfo* info) -{ - LodePNGText_cleanup(info); -} - -unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) -{ - char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); - char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); - if (!new_keys || !new_strings) - { - lodepng_free(new_keys); - lodepng_free(new_strings); - return 83; /*alloc fail*/ - } - - ++info->text_num; - info->text_keys = new_keys; - info->text_strings = new_strings; - - string_init(&info->text_keys[info->text_num - 1]); - string_set(&info->text_keys[info->text_num - 1], key); - - string_init(&info->text_strings[info->text_num - 1]); - string_set(&info->text_strings[info->text_num - 1], str); - - return 0; -} - -/******************************************************************************/ - -static void LodePNGIText_init(LodePNGInfo* info) -{ - info->itext_num = 0; - info->itext_keys = NULL; - info->itext_langtags = NULL; - info->itext_transkeys = NULL; - info->itext_strings = NULL; -} - -static void LodePNGIText_cleanup(LodePNGInfo* info) -{ - size_t i; - for (i = 0; i != info->itext_num; ++i) - { - string_cleanup(&info->itext_keys[i]); - string_cleanup(&info->itext_langtags[i]); - string_cleanup(&info->itext_transkeys[i]); - string_cleanup(&info->itext_strings[i]); - } - lodepng_free(info->itext_keys); - lodepng_free(info->itext_langtags); - lodepng_free(info->itext_transkeys); - lodepng_free(info->itext_strings); -} - -static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) -{ - size_t i = 0; - dest->itext_keys = 0; - dest->itext_langtags = 0; - dest->itext_transkeys = 0; - dest->itext_strings = 0; - dest->itext_num = 0; - for (i = 0; i != source->itext_num; ++i) - { - CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], - source->itext_transkeys[i], source->itext_strings[i])); - } - return 0; -} - -void lodepng_clear_itext(LodePNGInfo* info) -{ - LodePNGIText_cleanup(info); -} - -unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str) -{ - char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); - char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); - char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); - char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); - if (!new_keys || !new_langtags || !new_transkeys || !new_strings) - { - lodepng_free(new_keys); - lodepng_free(new_langtags); - lodepng_free(new_transkeys); - lodepng_free(new_strings); - return 83; /*alloc fail*/ - } - - ++info->itext_num; - info->itext_keys = new_keys; - info->itext_langtags = new_langtags; - info->itext_transkeys = new_transkeys; - info->itext_strings = new_strings; - - string_init(&info->itext_keys[info->itext_num - 1]); - string_set(&info->itext_keys[info->itext_num - 1], key); - - string_init(&info->itext_langtags[info->itext_num - 1]); - string_set(&info->itext_langtags[info->itext_num - 1], langtag); - - string_init(&info->itext_transkeys[info->itext_num - 1]); - string_set(&info->itext_transkeys[info->itext_num - 1], transkey); - - string_init(&info->itext_strings[info->itext_num - 1]); - string_set(&info->itext_strings[info->itext_num - 1], str); - - return 0; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -void lodepng_info_init(LodePNGInfo* info) -{ - lodepng_color_mode_init(&info->color); - info->interlace_method = 0; - info->compression_method = 0; - info->filter_method = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - info->background_defined = 0; - info->background_r = info->background_g = info->background_b = 0; - - LodePNGText_init(info); - LodePNGIText_init(info); - - info->time_defined = 0; - info->phys_defined = 0; - - LodePNGUnknownChunks_init(info); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -void lodepng_info_cleanup(LodePNGInfo* info) -{ - lodepng_color_mode_cleanup(&info->color); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - LodePNGText_cleanup(info); - LodePNGIText_cleanup(info); - - LodePNGUnknownChunks_cleanup(info); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) -{ - lodepng_info_cleanup(dest); - *dest = *source; - lodepng_color_mode_init(&dest->color); - CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); - CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); - - LodePNGUnknownChunks_init(dest); - CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - return 0; -} - -void lodepng_info_swap(LodePNGInfo* a, LodePNGInfo* b) -{ - LodePNGInfo temp = *a; - *a = *b; - *b = temp; -} - -/* ////////////////////////////////////////////////////////////////////////// */ - -/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ -static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) -{ - unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ - /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ - unsigned p = index & m; - in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ - in = in << (bits * (m - p)); - if (p == 0) out[index * bits / 8] = in; - else out[index * bits / 8] |= in; -} - -typedef struct ColorTree ColorTree; - -/* -One node of a color tree -This is the data structure used to count the number of unique colors and to get a palette -index for a color. It's like an octree, but because the alpha channel is used too, each -node has 16 instead of 8 children. -*/ -struct ColorTree -{ - ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ - int index; /*the payload. Only has a meaningful value if this is in the last level*/ -}; - -static void color_tree_init(ColorTree* tree) -{ - int i; - for (i = 0; i != 16; ++i) tree->children[i] = 0; - tree->index = -1; -} - -static void color_tree_cleanup(ColorTree* tree) -{ - int i; - for (i = 0; i != 16; ++i) - { - if (tree->children[i]) - { - color_tree_cleanup(tree->children[i]); - lodepng_free(tree->children[i]); - } - } -} - -/*returns -1 if color not present, its index otherwise*/ -static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - int bit = 0; - for (bit = 0; bit < 8; ++bit) - { - int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); - if (!tree->children[i]) return -1; - else tree = tree->children[i]; - } - return tree ? tree->index : -1; -} - -#ifdef LODEPNG_COMPILE_ENCODER -static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - return color_tree_get(tree, r, g, b, a) >= 0; -} -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/*color is not allowed to already exist. -Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")*/ -static void color_tree_add(ColorTree* tree, - unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) -{ - int bit; - for (bit = 0; bit < 8; ++bit) - { - int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); - if (!tree->children[i]) - { - tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); - color_tree_init(tree->children[i]); - } - tree = tree->children[i]; - } - tree->index = (int)index; -} - -/*put a pixel, given its RGBA color, into image of any color type*/ -static unsigned rgba8ToPixel(unsigned char* out, size_t i, - const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, - unsigned char r, unsigned char g, unsigned char b, unsigned char a) -{ - if (mode->colortype == LCT_GREY) - { - unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/; - if (mode->bitdepth == 8) out[i] = grey; - else if (mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = grey; - else - { - /*take the most significant bits of grey*/ - grey = (grey >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1); - addColorBits(out, i, mode->bitdepth, grey); - } - } - else if (mode->colortype == LCT_RGB) - { - if (mode->bitdepth == 8) - { - out[i * 3 + 0] = r; - out[i * 3 + 1] = g; - out[i * 3 + 2] = b; - } - else - { - out[i * 6 + 0] = out[i * 6 + 1] = r; - out[i * 6 + 2] = out[i * 6 + 3] = g; - out[i * 6 + 4] = out[i * 6 + 5] = b; - } - } - else if (mode->colortype == LCT_PALETTE) - { - int index = color_tree_get(tree, r, g, b, a); - if (index < 0) return 82; /*color not in palette*/ - if (mode->bitdepth == 8) out[i] = index; - else addColorBits(out, i, mode->bitdepth, (unsigned)index); - } - else if (mode->colortype == LCT_GREY_ALPHA) - { - unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/; - if (mode->bitdepth == 8) - { - out[i * 2 + 0] = grey; - out[i * 2 + 1] = a; - } - else if (mode->bitdepth == 16) - { - out[i * 4 + 0] = out[i * 4 + 1] = grey; - out[i * 4 + 2] = out[i * 4 + 3] = a; - } - } - else if (mode->colortype == LCT_RGBA) - { - if (mode->bitdepth == 8) - { - out[i * 4 + 0] = r; - out[i * 4 + 1] = g; - out[i * 4 + 2] = b; - out[i * 4 + 3] = a; - } - else - { - out[i * 8 + 0] = out[i * 8 + 1] = r; - out[i * 8 + 2] = out[i * 8 + 3] = g; - out[i * 8 + 4] = out[i * 8 + 5] = b; - out[i * 8 + 6] = out[i * 8 + 7] = a; - } - } - - return 0; /*no error*/ -} - -/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ -static void rgba16ToPixel(unsigned char* out, size_t i, - const LodePNGColorMode* mode, - unsigned short r, unsigned short g, unsigned short b, unsigned short a) -{ - if (mode->colortype == LCT_GREY) - { - unsigned short grey = r; /*((unsigned)r + g + b) / 3*/; - out[i * 2 + 0] = (grey >> 8) & 255; - out[i * 2 + 1] = grey & 255; - } - else if (mode->colortype == LCT_RGB) - { - out[i * 6 + 0] = (r >> 8) & 255; - out[i * 6 + 1] = r & 255; - out[i * 6 + 2] = (g >> 8) & 255; - out[i * 6 + 3] = g & 255; - out[i * 6 + 4] = (b >> 8) & 255; - out[i * 6 + 5] = b & 255; - } - else if (mode->colortype == LCT_GREY_ALPHA) - { - unsigned short grey = r; /*((unsigned)r + g + b) / 3*/; - out[i * 4 + 0] = (grey >> 8) & 255; - out[i * 4 + 1] = grey & 255; - out[i * 4 + 2] = (a >> 8) & 255; - out[i * 4 + 3] = a & 255; - } - else if (mode->colortype == LCT_RGBA) - { - out[i * 8 + 0] = (r >> 8) & 255; - out[i * 8 + 1] = r & 255; - out[i * 8 + 2] = (g >> 8) & 255; - out[i * 8 + 3] = g & 255; - out[i * 8 + 4] = (b >> 8) & 255; - out[i * 8 + 5] = b & 255; - out[i * 8 + 6] = (a >> 8) & 255; - out[i * 8 + 7] = a & 255; - } -} - -/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ -static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, - unsigned char* b, unsigned char* a, - const unsigned char* in, size_t i, - const LodePNGColorMode* mode) -{ - if (mode->colortype == LCT_GREY) - { - if (mode->bitdepth == 8) - { - *r = *g = *b = in[i]; - if (mode->key_defined && *r == mode->key_r) *a = 0; - else *a = 255; - } - else if (mode->bitdepth == 16) - { - *r = *g = *b = in[i * 2 + 0]; - if (mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; - else *a = 255; - } - else - { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = i * mode->bitdepth; - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - *r = *g = *b = (value * 255) / highest; - if (mode->key_defined && value == mode->key_r) *a = 0; - else *a = 255; - } - } - else if (mode->colortype == LCT_RGB) - { - if (mode->bitdepth == 8) - { - *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; - if (mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; - else *a = 255; - } - else - { - *r = in[i * 6 + 0]; - *g = in[i * 6 + 2]; - *b = in[i * 6 + 4]; - if (mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; - else *a = 255; - } - } - else if (mode->colortype == LCT_PALETTE) - { - unsigned index; - if (mode->bitdepth == 8) index = in[i]; - else - { - size_t j = i * mode->bitdepth; - index = readBitsFromReversedStream(&j, in, mode->bitdepth); - } - - if (index >= mode->palettesize) - { - /*This is an error according to the PNG spec, but common PNG decoders make it black instead. - Done here too, slightly faster due to no error handling needed.*/ - *r = *g = *b = 0; - *a = 255; - } - else - { - *r = mode->palette[index * 4 + 0]; - *g = mode->palette[index * 4 + 1]; - *b = mode->palette[index * 4 + 2]; - *a = mode->palette[index * 4 + 3]; - } - } - else if (mode->colortype == LCT_GREY_ALPHA) - { - if (mode->bitdepth == 8) - { - *r = *g = *b = in[i * 2 + 0]; - *a = in[i * 2 + 1]; - } - else - { - *r = *g = *b = in[i * 4 + 0]; - *a = in[i * 4 + 2]; - } - } - else if (mode->colortype == LCT_RGBA) - { - if (mode->bitdepth == 8) - { - *r = in[i * 4 + 0]; - *g = in[i * 4 + 1]; - *b = in[i * 4 + 2]; - *a = in[i * 4 + 3]; - } - else - { - *r = in[i * 8 + 0]; - *g = in[i * 8 + 2]; - *b = in[i * 8 + 4]; - *a = in[i * 8 + 6]; - } - } -} - -/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color -mode test cases, optimized to convert the colors much faster, when converting -to RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with -enough memory, if has_alpha is true the output is RGBA. mode has the color mode -of the input buffer.*/ -static void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels, - unsigned has_alpha, const unsigned char* in, - const LodePNGColorMode* mode) -{ - unsigned num_channels = has_alpha ? 4 : 3; - size_t i; - if (mode->colortype == LCT_GREY) - { - if (mode->bitdepth == 8) - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = buffer[1] = buffer[2] = in[i]; - if (has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255; - } - } - else if (mode->bitdepth == 16) - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = buffer[1] = buffer[2] = in[i * 2]; - if (has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; - } - } - else - { - unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ - size_t j = 0; - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); - buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; - if (has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; - } - } - } - else if (mode->colortype == LCT_RGB) - { - if (mode->bitdepth == 8) - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = in[i * 3 + 0]; - buffer[1] = in[i * 3 + 1]; - buffer[2] = in[i * 3 + 2]; - if (has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r - && buffer[1] == mode->key_g && buffer[2] == mode->key_b ? 0 : 255; - } - } - else - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = in[i * 6 + 0]; - buffer[1] = in[i * 6 + 2]; - buffer[2] = in[i * 6 + 4]; - if (has_alpha) buffer[3] = mode->key_defined - && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; - } - } - } - else if (mode->colortype == LCT_PALETTE) - { - unsigned index; - size_t j = 0; - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - if (mode->bitdepth == 8) index = in[i]; - else index = readBitsFromReversedStream(&j, in, mode->bitdepth); - - if (index >= mode->palettesize) - { - /*This is an error according to the PNG spec, but most PNG decoders make it black instead. - Done here too, slightly faster due to no error handling needed.*/ - buffer[0] = buffer[1] = buffer[2] = 0; - if (has_alpha) buffer[3] = 255; - } - else - { - buffer[0] = mode->palette[index * 4 + 0]; - buffer[1] = mode->palette[index * 4 + 1]; - buffer[2] = mode->palette[index * 4 + 2]; - if (has_alpha) buffer[3] = mode->palette[index * 4 + 3]; - } - } - } - else if (mode->colortype == LCT_GREY_ALPHA) - { - if (mode->bitdepth == 8) - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; - if (has_alpha) buffer[3] = in[i * 2 + 1]; - } - } - else - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; - if (has_alpha) buffer[3] = in[i * 4 + 2]; - } - } - } - else if (mode->colortype == LCT_RGBA) - { - if (mode->bitdepth == 8) - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = in[i * 4 + 0]; - buffer[1] = in[i * 4 + 1]; - buffer[2] = in[i * 4 + 2]; - if (has_alpha) buffer[3] = in[i * 4 + 3]; - } - } - else - { - for (i = 0; i != numpixels; ++i, buffer += num_channels) - { - buffer[0] = in[i * 8 + 0]; - buffer[1] = in[i * 8 + 2]; - buffer[2] = in[i * 8 + 4]; - if (has_alpha) buffer[3] = in[i * 8 + 6]; - } - } - } -} - -/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with -given color type, but the given color type must be 16-bit itself.*/ -static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, - const unsigned char* in, size_t i, const LodePNGColorMode* mode) -{ - if (mode->colortype == LCT_GREY) - { - *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; - if (mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; - else *a = 65535; - } - else if (mode->colortype == LCT_RGB) - { - *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; - *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; - *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; - if (mode->key_defined - && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r - && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g - && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; - else *a = 65535; - } - else if (mode->colortype == LCT_GREY_ALPHA) - { - *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; - *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; - } - else if (mode->colortype == LCT_RGBA) - { - *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; - *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; - *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; - *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; - } -} - -unsigned lodepng_convert(unsigned char* out, const unsigned char* in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, - unsigned w, unsigned h) -{ - size_t i; - ColorTree tree; - size_t numpixels = w * h; - - if (lodepng_color_mode_equal(mode_out, mode_in)) - { - size_t numbytes = lodepng_get_raw_size(w, h, mode_in); - for (i = 0; i != numbytes; ++i) out[i] = in[i]; - return 0; - } - - if (mode_out->colortype == LCT_PALETTE) - { - size_t palettesize = mode_out->palettesize; - const unsigned char* palette = mode_out->palette; - size_t palsize = 1u << mode_out->bitdepth; - /*if the user specified output palette but did not give the values, assume - they want the values of the input color type (assuming that one is palette). - Note that we never create a new palette ourselves.*/ - if (palettesize == 0) - { - palettesize = mode_in->palettesize; - palette = mode_in->palette; - } - if (palettesize < palsize) palsize = palettesize; - color_tree_init(&tree); - for (i = 0; i != palsize; ++i) - { - const unsigned char* p = &palette[i * 4]; - color_tree_add(&tree, p[0], p[1], p[2], p[3], i); - } - } - - if (mode_in->bitdepth == 16 && mode_out->bitdepth == 16) - { - for (i = 0; i != numpixels; ++i) - { - unsigned short r = 0, g = 0, b = 0, a = 0; - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); - rgba16ToPixel(out, i, mode_out, r, g, b, a); - } - } - else if (mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) - { - getPixelColorsRGBA8(out, numpixels, 1, in, mode_in); - } - else if (mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) - { - getPixelColorsRGBA8(out, numpixels, 0, in, mode_in); - } - else - { - unsigned char r = 0, g = 0, b = 0, a = 0; - for (i = 0; i != numpixels; ++i) - { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); - CERROR_TRY_RETURN(rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a)); - } - } - - if (mode_out->colortype == LCT_PALETTE) - { - color_tree_cleanup(&tree); - } - - return 0; /*no error*/ -} - -#ifdef LODEPNG_COMPILE_ENCODER - -void lodepng_color_profile_init(LodePNGColorProfile* profile) -{ - profile->colored = 0; - profile->key = 0; - profile->key_r = profile->key_g = profile->key_b = 0; - profile->alpha = 0; - profile->numcolors = 0; - profile->bits = 1; -} - -/*function used for debug purposes with C++*/ -/*void printColorProfile(LodePNGColorProfile* p) -{ - std::cout << "colored: " << (int)p->colored << ", "; - std::cout << "key: " << (int)p->key << ", "; - std::cout << "key_r: " << (int)p->key_r << ", "; - std::cout << "key_g: " << (int)p->key_g << ", "; - std::cout << "key_b: " << (int)p->key_b << ", "; - std::cout << "alpha: " << (int)p->alpha << ", "; - std::cout << "numcolors: " << (int)p->numcolors << ", "; - std::cout << "bits: " << (int)p->bits << std::endl; -}*/ - -/*Returns how many bits needed to represent given value (max 8 bit)*/ -static unsigned getValueRequiredBits(unsigned char value) -{ - if (value == 0 || value == 255) return 1; - /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ - if (value % 17 == 0) return value % 85 == 0 ? 2 : 4; - return 8; -} - -/*profile must already have been inited with mode. -It's ok to set some parameters of profile to done already.*/ -unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, - const unsigned char* in, unsigned w, unsigned h, - const LodePNGColorMode* mode) -{ - unsigned error = 0; - size_t i; - ColorTree tree; - size_t numpixels = w * h; - - unsigned colored_done = lodepng_is_greyscale_type(mode) ? 1 : 0; - unsigned alpha_done = lodepng_can_have_alpha(mode) ? 0 : 1; - unsigned numcolors_done = 0; - unsigned bpp = lodepng_get_bpp(mode); - unsigned bits_done = bpp == 1 ? 1 : 0; - unsigned maxnumcolors = 257; - unsigned sixteen = 0; - if (bpp <= 8) maxnumcolors = bpp == 1 ? 2 : (bpp == 2 ? 4 : (bpp == 4 ? 16 : 256)); - - color_tree_init(&tree); - - /*Check if the 16-bit input is truly 16-bit*/ - if (mode->bitdepth == 16) - { - unsigned short r, g, b, a; - for (i = 0; i != numpixels; ++i) - { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode); - if ((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || - (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ - { - sixteen = 1; - break; - } - } - } - - if (sixteen) - { - unsigned short r = 0, g = 0, b = 0, a = 0; - profile->bits = 16; - bits_done = numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ - - for (i = 0; i != numpixels; ++i) - { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode); - - if (!colored_done && (r != g || r != b)) - { - profile->colored = 1; - colored_done = 1; - } - - if (!alpha_done) - { - unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b); - if (a != 65535 && (a != 0 || (profile->key && !matchkey))) - { - profile->alpha = 1; - profile->key = 0; - alpha_done = 1; - } - else if (a == 0 && !profile->alpha && !profile->key) - { - profile->key = 1; - profile->key_r = r; - profile->key_g = g; - profile->key_b = b; - } - else if (a == 65535 && profile->key && matchkey) - { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - profile->alpha = 1; - profile->key = 0; - alpha_done = 1; - } - } - if (alpha_done && numcolors_done && colored_done && bits_done) break; - } - - if (profile->key && !profile->alpha) - { - for (i = 0; i != numpixels; ++i) - { - getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode); - if (a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) - { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - profile->alpha = 1; - profile->key = 0; - alpha_done = 1; - } - } - } - } - else /* < 16-bit */ - { - unsigned char r = 0, g = 0, b = 0, a = 0; - for (i = 0; i != numpixels; ++i) - { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode); - - if (!bits_done && profile->bits < 8) - { - /*only r is checked, < 8 bits is only relevant for greyscale*/ - unsigned bits = getValueRequiredBits(r); - if (bits > profile->bits) profile->bits = bits; - } - bits_done = (profile->bits >= bpp); - - if (!colored_done && (r != g || r != b)) - { - profile->colored = 1; - colored_done = 1; - if (profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ - } - - if (!alpha_done) - { - unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b); - if (a != 255 && (a != 0 || (profile->key && !matchkey))) - { - profile->alpha = 1; - profile->key = 0; - alpha_done = 1; - if (profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - else if (a == 0 && !profile->alpha && !profile->key) - { - profile->key = 1; - profile->key_r = r; - profile->key_g = g; - profile->key_b = b; - } - else if (a == 255 && profile->key && matchkey) - { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - profile->alpha = 1; - profile->key = 0; - alpha_done = 1; - if (profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - } - - if (!numcolors_done) - { - if (!color_tree_has(&tree, r, g, b, a)) - { - color_tree_add(&tree, r, g, b, a, profile->numcolors); - if (profile->numcolors < 256) - { - unsigned char* p = profile->palette; - unsigned n = profile->numcolors; - p[n * 4 + 0] = r; - p[n * 4 + 1] = g; - p[n * 4 + 2] = b; - p[n * 4 + 3] = a; - } - ++profile->numcolors; - numcolors_done = profile->numcolors >= maxnumcolors; - } - } - - if (alpha_done && numcolors_done && colored_done && bits_done) break; - } - - if (profile->key && !profile->alpha) - { - for (i = 0; i != numpixels; ++i) - { - getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode); - if (a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) - { - /* Color key cannot be used if an opaque pixel also has that RGB color. */ - profile->alpha = 1; - profile->key = 0; - alpha_done = 1; - if (profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - } - } - - /*make the profile's key always 16-bit for consistency - repeat each byte twice*/ - profile->key_r += (profile->key_r << 8); - profile->key_g += (profile->key_g << 8); - profile->key_b += (profile->key_b << 8); - } - - color_tree_cleanup(&tree); - return error; -} - -/*Automatically chooses color type that gives smallest amount of bits in the -output image, e.g. grey if there are only greyscale pixels, palette if there -are less than 256 colors, ... -Updates values of mode with a potentially smaller color model. mode_out should -contain the user chosen color model, but will be overwritten with the new chosen one.*/ -unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, - const unsigned char* image, unsigned w, unsigned h, - const LodePNGColorMode* mode_in) -{ - LodePNGColorProfile prof; - unsigned error = 0; - unsigned i, n, palettebits, palette_ok; - - lodepng_color_profile_init(&prof); - error = lodepng_get_color_profile(&prof, image, w, h, mode_in); - if (error) return error; - mode_out->key_defined = 0; - - if (prof.key && w * h <= 16) - { - prof.alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ - prof.key = 0; - if (prof.bits < 8) prof.bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ - } - n = prof.numcolors; - palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); - palette_ok = n <= 256 && prof.bits <= 8; - if (w * h < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ - if (!prof.colored && prof.bits <= palettebits) palette_ok = 0; /*grey is less overhead*/ - - if (palette_ok) - { - unsigned char* p = prof.palette; - lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ - for (i = 0; i != prof.numcolors; ++i) - { - error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); - if (error) break; - } - - mode_out->colortype = LCT_PALETTE; - mode_out->bitdepth = palettebits; - - if (mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize - && mode_in->bitdepth == mode_out->bitdepth) - { - /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ - lodepng_color_mode_cleanup(mode_out); - lodepng_color_mode_copy(mode_out, mode_in); - } - } - else /*8-bit or 16-bit per channel*/ - { - mode_out->bitdepth = prof.bits; - mode_out->colortype = prof.alpha ? (prof.colored ? LCT_RGBA : LCT_GREY_ALPHA) - : (prof.colored ? LCT_RGB : LCT_GREY); - - if (prof.key) - { - unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/ - mode_out->key_r = prof.key_r & mask; - mode_out->key_g = prof.key_g & mask; - mode_out->key_b = prof.key_b & mask; - mode_out->key_defined = 1; - } - } - - return error; -} - -#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ - -/* -Paeth predicter, used by PNG filter type 4 -The parameters are of type short, but should come from unsigned chars, the shorts -are only needed to make the paeth calculation correct. -*/ -static unsigned char paethPredictor(short a, short b, short c) -{ - short pa = abs(b - c); - short pb = abs(a - c); - short pc = abs(a + b - c - c); - - if (pc < pa && pc < pb) return (unsigned char)c; - else if (pb < pa) return (unsigned char)b; - else return (unsigned char)a; -} - -/*shared values used by multiple Adam7 related functions*/ - -static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ -static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ -static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ -static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ - -/* -Outputs various dimensions and positions in the image related to the Adam7 reduced images. -passw: output containing the width of the 7 passes -passh: output containing the height of the 7 passes -filter_passstart: output containing the index of the start and end of each - reduced image with filter bytes -padded_passstart output containing the index of the start and end of each - reduced image when without filter bytes but with padded scanlines -passstart: output containing the index of the start and end of each reduced - image without padding between scanlines, but still padding between the images -w, h: width and height of non-interlaced image -bpp: bits per pixel -"padded" is only relevant if bpp is less than 8 and a scanline or image does not - end at a full byte -*/ -static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], - size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) -{ - /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ - unsigned i; - - /*calculate width and height in pixels of each pass*/ - for (i = 0; i != 7; ++i) - { - passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; - passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; - if (passw[i] == 0) passh[i] = 0; - if (passh[i] == 0) passw[i] = 0; - } - - filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; - for (i = 0; i != 7; ++i) - { - /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ - filter_passstart[i + 1] = filter_passstart[i] - + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); - /*bits padded if needed to fill full byte at end of each scanline*/ - padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); - /*only padded at end of reduced image*/ - passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; - } -} - -#ifdef LODEPNG_COMPILE_DECODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Decoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*read the information from the header and store it in the LodePNGInfo. return value is error*/ -unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, - const unsigned char* in, size_t insize) -{ - LodePNGInfo* info = &state->info_png; - if (insize == 0 || in == 0) - { - CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ - } - if (insize < 33) - { - CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ - } - - /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ - lodepng_info_cleanup(info); - lodepng_info_init(info); - - if (in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 - || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) - { - CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ - } - if (lodepng_chunk_length(in + 8) != 13) - { - CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ - } - if (!lodepng_chunk_type_equals(in + 8, "IHDR")) - { - CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ - } - - /*read the values given in the header*/ - *w = lodepng_read32bitInt(&in[16]); - *h = lodepng_read32bitInt(&in[20]); - info->color.bitdepth = in[24]; - info->color.colortype = (LodePNGColorType)in[25]; - info->compression_method = in[26]; - info->filter_method = in[27]; - info->interlace_method = in[28]; - - if (*w == 0 || *h == 0) - { - CERROR_RETURN_ERROR(state->error, 93); - } - - if (!state->decoder.ignore_crc) - { - unsigned CRC = lodepng_read32bitInt(&in[29]); - unsigned checksum = lodepng_crc32(&in[12], 17); - if (CRC != checksum) - { - CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ - } - } - - /*error: only compression method 0 is allowed in the specification*/ - if (info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); - /*error: only filter method 0 is allowed in the specification*/ - if (info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); - /*error: only interlace methods 0 and 1 exist in the specification*/ - if (info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); - - state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); - return state->error; -} - -static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, - size_t bytewidth, unsigned char filterType, size_t length) -{ - /* - For PNG filter method 0 - unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, - the filter works byte per byte (bytewidth = 1) - precon is the previous unfiltered scanline, recon the result, scanline the current one - the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead - recon and scanline MAY be the same memory address! precon must be disjoint. - */ - - size_t i; - switch (filterType) - { - case 0: - for (i = 0; i != length; ++i) recon[i] = scanline[i]; - break; - case 1: - for (i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for (i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth]; - break; - case 2: - if (precon) - { - for (i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; - } - else - { - for (i = 0; i != length; ++i) recon[i] = scanline[i]; - } - break; - case 3: - if (precon) - { - for (i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1); - for (i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1); - } - else - { - for (i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; - for (i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1); - } - break; - case 4: - if (precon) - { - for (i = 0; i != bytewidth; ++i) - { - recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ - } - for (i = bytewidth; i < length; ++i) - { - recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); - } - } - else - { - for (i = 0; i != bytewidth; ++i) - { - recon[i] = scanline[i]; - } - for (i = bytewidth; i < length; ++i) - { - /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ - recon[i] = (scanline[i] + recon[i - bytewidth]); - } - } - break; - default: return 36; /*error: unexisting filter type given*/ - } - return 0; -} - -static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) -{ - /* - For PNG filter method 0 - this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) - out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline - w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel - in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) - */ - - unsigned y; - unsigned char* prevline = 0; - - /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - size_t bytewidth = (bpp + 7) / 8; - size_t linebytes = (w * bpp + 7) / 8; - - for (y = 0; y < h; ++y) - { - size_t outindex = linebytes * y; - size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - unsigned char filterType = in[inindex]; - - CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); - - prevline = &out[outindex]; - } - - return 0; -} - -/* -in: Adam7 interlaced image, with no padding bits between scanlines, but between - reduced images so that each reduced image starts at a byte. -out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h -bpp: bits per pixel -out has the following size in bits: w * h * bpp. -in is possibly bigger due to padding bits between reduced images. -out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation -(because that's likely a little bit faster) -NOTE: comments about padding bits are only relevant if bpp < 8 -*/ -static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) -{ - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if (bpp >= 8) - { - for (i = 0; i != 7; ++i) - { - unsigned x, y, b; - size_t bytewidth = bpp / 8; - for (y = 0; y < passh[i]; ++y) - for (x = 0; x < passw[i]; ++x) - { - size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; - size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; - for (b = 0; b < bytewidth; ++b) - { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } - else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ - { - for (i = 0; i != 7; ++i) - { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for (y = 0; y < passh[i]; ++y) - for (x = 0; x < passw[i]; ++x) - { - ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; - for (b = 0; b < bpp; ++b) - { - unsigned char bit = readBitFromReversedStream(&ibp, in); - /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/ - setBitOfReversedStream0(&obp, out, bit); - } - } - } - } -} - -static void removePaddingBits(unsigned char* out, const unsigned char* in, - size_t olinebits, size_t ilinebits, unsigned h) -{ - /* - After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need - to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers - for the Adam7 code, the color convert code and the output to the user. - in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must - have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits - also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 - only useful if (ilinebits - olinebits) is a value in the range 1..7 - */ - unsigned y; - size_t diff = ilinebits - olinebits; - size_t ibp = 0, obp = 0; /*input and output bit pointers*/ - for (y = 0; y < h; ++y) - { - size_t x; - for (x = 0; x < olinebits; ++x) - { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - ibp += diff; - } -} - -/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from -the IDAT chunks (with filter index bytes and possible padding bits) -return value is error*/ -static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, - unsigned w, unsigned h, const LodePNGInfo* info_png) -{ - /* - This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. - Steps: - *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8) - *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace - NOTE: the in buffer will be overwritten with intermediate data! - */ - unsigned bpp = lodepng_get_bpp(&info_png->color); - if (bpp == 0) return 31; /*error: invalid colortype*/ - - if (info_png->interlace_method == 0) - { - if (bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) - { - CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); - removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h); - } - /*we can immediately filter into the out buffer, no other steps needed*/ - else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); - } - else /*interlace_method is 1 (Adam7)*/ - { - unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - for (i = 0; i != 7; ++i) - { - CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); - /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, - move bytes instead of bits or move not at all*/ - if (bpp < 8) - { - /*remove padding bits in scanlines; after this there still may be padding - bits between the different reduced images: each reduced image still starts nicely at a byte*/ - removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, - ((passw[i] * bpp + 7) / 8) * 8, passh[i]); - } - } - - Adam7_deinterlace(out, in, w, h, bpp); - } - - return 0; -} - -static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) -{ - unsigned pos = 0, i; - if (color->palette) lodepng_free(color->palette); - color->palettesize = chunkLength / 3; - color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize); - if (!color->palette && color->palettesize) - { - color->palettesize = 0; - return 83; /*alloc fail*/ - } - if (color->palettesize > 256) return 38; /*error: palette too big*/ - - for (i = 0; i != color->palettesize; ++i) - { - color->palette[4 * i + 0] = data[pos++]; /*R*/ - color->palette[4 * i + 1] = data[pos++]; /*G*/ - color->palette[4 * i + 2] = data[pos++]; /*B*/ - color->palette[4 * i + 3] = 255; /*alpha*/ - } - - return 0; /* OK */ -} - -static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) -{ - unsigned i; - if (color->colortype == LCT_PALETTE) - { - /*error: more alpha values given than there are palette entries*/ - if (chunkLength > color->palettesize) return 38; - - for (i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; - } - else if (color->colortype == LCT_GREY) - { - /*error: this chunk must be 2 bytes for greyscale image*/ - if (chunkLength != 2) return 30; - - color->key_defined = 1; - color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; - } - else if (color->colortype == LCT_RGB) - { - /*error: this chunk must be 6 bytes for RGB image*/ - if (chunkLength != 6) return 41; - - color->key_defined = 1; - color->key_r = 256u * data[0] + data[1]; - color->key_g = 256u * data[2] + data[3]; - color->key_b = 256u * data[4] + data[5]; - } - else return 42; /*error: tRNS chunk not allowed for other color models*/ - - return 0; /* OK */ -} - - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*background color chunk (bKGD)*/ -static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) -{ - if (info->color.colortype == LCT_PALETTE) - { - /*error: this chunk must be 1 byte for indexed color image*/ - if (chunkLength != 1) return 43; - - info->background_defined = 1; - info->background_r = info->background_g = info->background_b = data[0]; - } - else if (info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) - { - /*error: this chunk must be 2 bytes for greyscale image*/ - if (chunkLength != 2) return 44; - - info->background_defined = 1; - info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; - } - else if (info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) - { - /*error: this chunk must be 6 bytes for greyscale image*/ - if (chunkLength != 6) return 45; - - info->background_defined = 1; - info->background_r = 256u * data[0] + data[1]; - info->background_g = 256u * data[2] + data[3]; - info->background_b = 256u * data[4] + data[5]; - } - - return 0; /* OK */ -} - -/*text chunk (tEXt)*/ -static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) -{ - unsigned error = 0; - char *key = 0, *str = 0; - unsigned i; - - while (!error) /*not really a while loop, only used to break on error*/ - { - unsigned length, string2_begin; - - length = 0; - while (length < chunkLength && data[length] != 0) ++length; - /*even though it's not allowed by the standard, no error is thrown if - there's no null termination char, if the text is empty*/ - if (length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if (!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - key[length] = 0; - for (i = 0; i != length; ++i) key[i] = (char)data[i]; - - string2_begin = length + 1; /*skip keyword null terminator*/ - - length = chunkLength < string2_begin ? 0 : chunkLength - string2_begin; - str = (char*)lodepng_malloc(length + 1); - if (!str) CERROR_BREAK(error, 83); /*alloc fail*/ - - str[length] = 0; - for (i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i]; - - error = lodepng_add_text(info, key, str); - - break; - } - - lodepng_free(key); - lodepng_free(str); - - return error; -} - -/*compressed text chunk (zTXt)*/ -static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, - const unsigned char* data, size_t chunkLength) -{ - unsigned error = 0; - unsigned i; - - unsigned length, string2_begin; - char *key = 0; - ucvector decoded; - - ucvector_init(&decoded); - - while (!error) /*not really a while loop, only used to break on error*/ - { - for (length = 0; length < chunkLength && data[length] != 0; ++length); - if (length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ - if (length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if (!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - key[length] = 0; - for (i = 0; i != length; ++i) key[i] = (char)data[i]; - - if (data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ - - string2_begin = length + 2; - if (string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ - - length = chunkLength - string2_begin; - /*will fail if zlib error, e.g. if length is too small*/ - error = zlib_decompress(&decoded.data, &decoded.size, - (unsigned char*)(&data[string2_begin]), - length, zlibsettings); - if (error) break; - ucvector_push_back(&decoded, 0); - - error = lodepng_add_text(info, key, (char*)decoded.data); - - break; - } - - lodepng_free(key); - ucvector_cleanup(&decoded); - - return error; -} - -/*international text chunk (iTXt)*/ -static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, - const unsigned char* data, size_t chunkLength) -{ - unsigned error = 0; - unsigned i; - - unsigned length, begin, compressed; - char *key = 0, *langtag = 0, *transkey = 0; - ucvector decoded; - ucvector_init(&decoded); - - while (!error) /*not really a while loop, only used to break on error*/ - { - /*Quick check if the chunk length isn't too small. Even without check - it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ - if (chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ - - /*read the key*/ - for (length = 0; length < chunkLength && data[length] != 0; ++length); - if (length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ - if (length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ - - key = (char*)lodepng_malloc(length + 1); - if (!key) CERROR_BREAK(error, 83); /*alloc fail*/ - - key[length] = 0; - for (i = 0; i != length; ++i) key[i] = (char)data[i]; - - /*read the compression method*/ - compressed = data[length + 1]; - if (data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ - - /*even though it's not allowed by the standard, no error is thrown if - there's no null termination char, if the text is empty for the next 3 texts*/ - - /*read the langtag*/ - begin = length + 3; - length = 0; - for (i = begin; i < chunkLength && data[i] != 0; ++i) ++length; - - langtag = (char*)lodepng_malloc(length + 1); - if (!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ - - langtag[length] = 0; - for (i = 0; i != length; ++i) langtag[i] = (char)data[begin + i]; - - /*read the transkey*/ - begin += length + 1; - length = 0; - for (i = begin; i < chunkLength && data[i] != 0; ++i) ++length; - - transkey = (char*)lodepng_malloc(length + 1); - if (!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ - - transkey[length] = 0; - for (i = 0; i != length; ++i) transkey[i] = (char)data[begin + i]; - - /*read the actual text*/ - begin += length + 1; - - length = chunkLength < begin ? 0 : chunkLength - begin; - - if (compressed) - { - /*will fail if zlib error, e.g. if length is too small*/ - error = zlib_decompress(&decoded.data, &decoded.size, - (unsigned char*)(&data[begin]), - length, zlibsettings); - if (error) break; - if (decoded.allocsize < decoded.size) decoded.allocsize = decoded.size; - ucvector_push_back(&decoded, 0); - } - else - { - if (!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/); - - decoded.data[length] = 0; - for (i = 0; i != length; ++i) decoded.data[i] = data[begin + i]; - } - - error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data); - - break; - } - - lodepng_free(key); - lodepng_free(langtag); - lodepng_free(transkey); - ucvector_cleanup(&decoded); - - return error; -} - -static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) -{ - if (chunkLength != 7) return 73; /*invalid tIME chunk size*/ - - info->time_defined = 1; - info->time.year = 256u * data[0] + data[1]; - info->time.month = data[2]; - info->time.day = data[3]; - info->time.hour = data[4]; - info->time.minute = data[5]; - info->time.second = data[6]; - - return 0; /* OK */ -} - -static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) -{ - if (chunkLength != 9) return 74; /*invalid pHYs chunk size*/ - - info->phys_defined = 1; - info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; - info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; - info->phys_unit = data[8]; - - return 0; /* OK */ -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ -static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize) -{ - unsigned char IEND = 0; - const unsigned char* chunk; - size_t i; - ucvector idat; /*the data from idat chunks*/ - ucvector scanlines; - size_t predict; - size_t numpixels; - size_t outsize = 0; - - /*for unknown chunk order*/ - unsigned unknown = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - - /*provide some proper output values if error will happen*/ - *out = 0; - - state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ - if (state->error) return; - - numpixels = *w * *h; - - /*multiplication overflow*/ - if (*h != 0 && numpixels / *h != *w) CERROR_RETURN(state->error, 92); - /*multiplication overflow possible further below. Allows up to 2^31-1 pixel - bytes with 16-bit RGBA, the rest is room for filter bytes.*/ - if (numpixels > 268435455) CERROR_RETURN(state->error, 92); - - ucvector_init(&idat); - chunk = &in[33]; /*first byte of the first chunk after the header*/ - - /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. - IDAT data is put at the start of the in buffer*/ - while (!IEND && !state->error) - { - unsigned chunkLength; - const unsigned char* data; /*the data in the chunk*/ - - /*error: size of the in buffer too small to contain next chunk*/ - if ((size_t)((chunk - in) + 12) > insize || chunk < in) CERROR_BREAK(state->error, 30); - - /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ - chunkLength = lodepng_chunk_length(chunk); - /*error: chunk length larger than the max PNG chunk size*/ - if (chunkLength > 2147483647) CERROR_BREAK(state->error, 63); - - if ((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) - { - CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ - } - - data = lodepng_chunk_data_const(chunk); - - /*IDAT chunk, containing compressed image data*/ - if (lodepng_chunk_type_equals(chunk, "IDAT")) - { - size_t oldsize = idat.size; - if (!ucvector_resize(&idat, oldsize + chunkLength)) CERROR_BREAK(state->error, 83 /*alloc fail*/); - for (i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i]; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - critical_pos = 3; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } - /*IEND chunk*/ - else if (lodepng_chunk_type_equals(chunk, "IEND")) - { - IEND = 1; - } - /*palette chunk (PLTE)*/ - else if (lodepng_chunk_type_equals(chunk, "PLTE")) - { - state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); - if (state->error) break; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - critical_pos = 2; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } - /*palette transparency chunk (tRNS)*/ - else if (lodepng_chunk_type_equals(chunk, "tRNS")) - { - state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); - if (state->error) break; - } -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*background color chunk (bKGD)*/ - else if (lodepng_chunk_type_equals(chunk, "bKGD")) - { - state->error = readChunk_bKGD(&state->info_png, data, chunkLength); - if (state->error) break; - } - /*text chunk (tEXt)*/ - else if (lodepng_chunk_type_equals(chunk, "tEXt")) - { - if (state->decoder.read_text_chunks) - { - state->error = readChunk_tEXt(&state->info_png, data, chunkLength); - if (state->error) break; - } - } - /*compressed text chunk (zTXt)*/ - else if (lodepng_chunk_type_equals(chunk, "zTXt")) - { - if (state->decoder.read_text_chunks) - { - state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); - if (state->error) break; - } - } - /*international text chunk (iTXt)*/ - else if (lodepng_chunk_type_equals(chunk, "iTXt")) - { - if (state->decoder.read_text_chunks) - { - state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); - if (state->error) break; - } - } - else if (lodepng_chunk_type_equals(chunk, "tIME")) - { - state->error = readChunk_tIME(&state->info_png, data, chunkLength); - if (state->error) break; - } - else if (lodepng_chunk_type_equals(chunk, "pHYs")) - { - state->error = readChunk_pHYs(&state->info_png, data, chunkLength); - if (state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - else /*it's not an implemented chunk type, so ignore it: skip over the data*/ - { - /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ - if (!lodepng_chunk_ancillary(chunk)) CERROR_BREAK(state->error, 69); - - unknown = 1; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - if (state->decoder.remember_unknown_chunks) - { - state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], - &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); - if (state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - } - - if (!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ - { - if (lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ - } - - if (!IEND) chunk = lodepng_chunk_next_const(chunk); - } - - ucvector_init(&scanlines); - /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. - If the decompressed size does not match the prediction, the image must be corrupt.*/ - if (state->info_png.interlace_method == 0) - { - /*The extra *h is added because this are the filter bytes every scanline starts with*/ - predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color) + *h; - } - else - { - /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/ - const LodePNGColorMode* color = &state->info_png.color; - predict = 0; - predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3); - if (*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color) + ((*h + 7) >> 3); - predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color) + ((*h + 3) >> 3); - if (*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color) + ((*h + 3) >> 2); - predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color) + ((*h + 1) >> 2); - if (*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color) + ((*h + 1) >> 1); - predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color) + ((*h + 0) >> 1); - } - if (!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/ - if (!state->error) - { - state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data, - idat.size, &state->decoder.zlibsettings); - if (!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/ - } - ucvector_cleanup(&idat); - - if (!state->error) - { - outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); - *out = (unsigned char*)lodepng_malloc(outsize); - if (!*out) state->error = 83; /*alloc fail*/ - } - if (!state->error) - { - for (i = 0; i < outsize; i++) (*out)[i] = 0; - state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png); - } - ucvector_cleanup(&scanlines); -} - -unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize) -{ - *out = 0; - decodeGeneric(out, w, h, state, in, insize); - if (state->error) return state->error; - if (!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) - { - /*same color type, no copying or converting of data needed*/ - /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype - the raw image has to the end user*/ - if (!state->decoder.color_convert) - { - state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); - if (state->error) return state->error; - } - } - else - { - /*color conversion needed; sort of copy of the data*/ - unsigned char* data = *out; - size_t outsize; - - /*TODO: check if this works according to the statement in the documentation: "The converter can convert - from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/ - if (!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) - && !(state->info_raw.bitdepth == 8)) - { - return 56; /*unsupported color mode conversion*/ - } - - outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); - *out = (unsigned char*)lodepng_malloc(outsize); - if (!(*out)) - { - state->error = 83; /*alloc fail*/ - } - else state->error = lodepng_convert(*out, data, &state->info_raw, - &state->info_png.color, *w, *h); - lodepng_free(data); - } - return state->error; -} - -unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, - size_t insize, LodePNGColorType colortype, unsigned bitdepth) -{ - unsigned error; - LodePNGState state; - lodepng_state_init(&state); - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - error = lodepng_decode(out, w, h, &state, in, insize); - lodepng_state_cleanup(&state); - return error; -} - -unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) -{ - return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); -} - -unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) -{ - return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, - LodePNGColorType colortype, unsigned bitdepth) -{ - unsigned char* buffer = 0; - size_t buffersize; - unsigned error; - error = lodepng_load_file(&buffer, &buffersize, filename); - if (!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); - lodepng_free(buffer); - return error; -} - -unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) -{ - return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); -} - -unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) -{ - return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); -} -#endif /*LODEPNG_COMPILE_DISK*/ - -void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) -{ - settings->color_convert = 1; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - settings->read_text_chunks = 1; - settings->remember_unknown_chunks = 0; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - settings->ignore_crc = 0; - lodepng_decompress_settings_init(&settings->zlibsettings); -} - -#endif /*LODEPNG_COMPILE_DECODER*/ - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) - -void lodepng_state_init(LodePNGState* state) -{ -#ifdef LODEPNG_COMPILE_DECODER - lodepng_decoder_settings_init(&state->decoder); -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER - lodepng_encoder_settings_init(&state->encoder); -#endif /*LODEPNG_COMPILE_ENCODER*/ - lodepng_color_mode_init(&state->info_raw); - lodepng_info_init(&state->info_png); - state->error = 1; -} - -void lodepng_state_cleanup(LodePNGState* state) -{ - lodepng_color_mode_cleanup(&state->info_raw); - lodepng_info_cleanup(&state->info_png); -} - -void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) -{ - lodepng_state_cleanup(dest); - *dest = *source; - lodepng_color_mode_init(&dest->info_raw); - lodepng_info_init(&dest->info_png); - dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if (dest->error) return; - dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if (dest->error) return; -} - -#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ - -#ifdef LODEPNG_COMPILE_ENCODER - -/* ////////////////////////////////////////////////////////////////////////// */ -/* / PNG Encoder / */ -/* ////////////////////////////////////////////////////////////////////////// */ - -/*chunkName must be string of 4 characters*/ -static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) -{ - CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data)); - out->allocsize = out->size; /*fix the allocsize again*/ - return 0; -} - -static void writeSignature(ucvector* out) -{ - /*8 bytes PNG signature, aka the magic bytes*/ - ucvector_push_back(out, 137); - ucvector_push_back(out, 80); - ucvector_push_back(out, 78); - ucvector_push_back(out, 71); - ucvector_push_back(out, 13); - ucvector_push_back(out, 10); - ucvector_push_back(out, 26); - ucvector_push_back(out, 10); -} - -static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) -{ - unsigned error = 0; - ucvector header; - ucvector_init(&header); - - lodepng_add32bitInt(&header, w); /*width*/ - lodepng_add32bitInt(&header, h); /*height*/ - ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/ - ucvector_push_back(&header, (unsigned char)colortype); /*color type*/ - ucvector_push_back(&header, 0); /*compression method*/ - ucvector_push_back(&header, 0); /*filter method*/ - ucvector_push_back(&header, interlace_method); /*interlace method*/ - - error = addChunk(out, "IHDR", header.data, header.size); - ucvector_cleanup(&header); - - return error; -} - -static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) -{ - unsigned error = 0; - size_t i; - ucvector PLTE; - ucvector_init(&PLTE); - for (i = 0; i != info->palettesize * 4; ++i) - { - /*add all channels except alpha channel*/ - if (i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]); - } - error = addChunk(out, "PLTE", PLTE.data, PLTE.size); - ucvector_cleanup(&PLTE); - - return error; -} - -static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) -{ - unsigned error = 0; - size_t i; - ucvector tRNS; - ucvector_init(&tRNS); - if (info->colortype == LCT_PALETTE) - { - size_t amount = info->palettesize; - /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ - for (i = info->palettesize; i != 0; --i) - { - if (info->palette[4 * (i - 1) + 3] == 255) --amount; - else break; - } - /*add only alpha channel*/ - for (i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]); - } - else if (info->colortype == LCT_GREY) - { - if (info->key_defined) - { - ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255)); - } - } - else if (info->colortype == LCT_RGB) - { - if (info->key_defined) - { - ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8)); - ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255)); - } - } - - error = addChunk(out, "tRNS", tRNS.data, tRNS.size); - ucvector_cleanup(&tRNS); - - return error; -} - -static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, - LodePNGCompressSettings* zlibsettings) -{ - ucvector zlibdata; - unsigned error = 0; - - /*compress with the Zlib compressor*/ - ucvector_init(&zlibdata); - error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings); - if (!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size); - ucvector_cleanup(&zlibdata); - - return error; -} - -static unsigned addChunk_IEND(ucvector* out) -{ - unsigned error = 0; - error = addChunk(out, "IEND", 0, 0); - return error; -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - -static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) -{ - unsigned error = 0; - size_t i; - ucvector text; - ucvector_init(&text); - for (i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]); - if (i < 1 || i > 79) return 89; /*error: invalid keyword size*/ - ucvector_push_back(&text, 0); /*0 termination char*/ - for (i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]); - error = addChunk(out, "tEXt", text.data, text.size); - ucvector_cleanup(&text); - - return error; -} - -static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, - LodePNGCompressSettings* zlibsettings) -{ - unsigned error = 0; - ucvector data, compressed; - size_t i, textsize = strlen(textstring); - - ucvector_init(&data); - ucvector_init(&compressed); - for (i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]); - if (i < 1 || i > 79) return 89; /*error: invalid keyword size*/ - ucvector_push_back(&data, 0); /*0 termination char*/ - ucvector_push_back(&data, 0); /*compression method: 0*/ - - error = zlib_compress(&compressed.data, &compressed.size, - (unsigned char*)textstring, textsize, zlibsettings); - if (!error) - { - for (i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]); - error = addChunk(out, "zTXt", data.data, data.size); - } - - ucvector_cleanup(&compressed); - ucvector_cleanup(&data); - return error; -} - -static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag, - const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) -{ - unsigned error = 0; - ucvector data; - size_t i, textsize = strlen(textstring); - - ucvector_init(&data); - - for (i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]); - if (i < 1 || i > 79) return 89; /*error: invalid keyword size*/ - ucvector_push_back(&data, 0); /*null termination char*/ - ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/ - ucvector_push_back(&data, 0); /*compression method*/ - for (i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]); - ucvector_push_back(&data, 0); /*null termination char*/ - for (i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]); - ucvector_push_back(&data, 0); /*null termination char*/ - - if (compressed) - { - ucvector compressed_data; - ucvector_init(&compressed_data); - error = zlib_compress(&compressed_data.data, &compressed_data.size, - (unsigned char*)textstring, textsize, zlibsettings); - if (!error) - { - for (i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]); - } - ucvector_cleanup(&compressed_data); - } - else /*not compressed*/ - { - for (i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]); - } - - if (!error) error = addChunk(out, "iTXt", data.data, data.size); - ucvector_cleanup(&data); - return error; -} - -static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) -{ - unsigned error = 0; - ucvector bKGD; - ucvector_init(&bKGD); - if (info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) - { - ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); - } - else if (info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) - { - ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8)); - ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255)); - } - else if (info->color.colortype == LCT_PALETTE) - { - ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/ - } - - error = addChunk(out, "bKGD", bKGD.data, bKGD.size); - ucvector_cleanup(&bKGD); - - return error; -} - -static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) -{ - unsigned error = 0; - unsigned char* data = (unsigned char*)lodepng_malloc(7); - if (!data) return 83; /*alloc fail*/ - data[0] = (unsigned char)(time->year >> 8); - data[1] = (unsigned char)(time->year & 255); - data[2] = (unsigned char)time->month; - data[3] = (unsigned char)time->day; - data[4] = (unsigned char)time->hour; - data[5] = (unsigned char)time->minute; - data[6] = (unsigned char)time->second; - error = addChunk(out, "tIME", data, 7); - lodepng_free(data); - return error; -} - -static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) -{ - unsigned error = 0; - ucvector data; - ucvector_init(&data); - - lodepng_add32bitInt(&data, info->phys_x); - lodepng_add32bitInt(&data, info->phys_y); - ucvector_push_back(&data, info->phys_unit); - - error = addChunk(out, "pHYs", data.data, data.size); - ucvector_cleanup(&data); - - return error; -} - -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, - size_t length, size_t bytewidth, unsigned char filterType) -{ - size_t i; - switch (filterType) - { - case 0: /*None*/ - for (i = 0; i != length; ++i) out[i] = scanline[i]; - break; - case 1: /*Sub*/ - for (i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for (i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; - break; - case 2: /*Up*/ - if (prevline) - { - for (i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; - } - else - { - for (i = 0; i != length; ++i) out[i] = scanline[i]; - } - break; - case 3: /*Average*/ - if (prevline) - { - for (i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); - for (i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); - } - else - { - for (i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - for (i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); - } - break; - case 4: /*Paeth*/ - if (prevline) - { - /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ - for (i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); - for (i = bytewidth; i < length; ++i) - { - out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); - } - } - else - { - for (i = 0; i != bytewidth; ++i) out[i] = scanline[i]; - /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ - for (i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); - } - break; - default: return; /*unexisting filter type given*/ - } -} - -/* log2 approximation. A slight bit faster than std::log. */ -static float flog2(float f) -{ - float result = 0; - while (f > 32) { result += 4; f /= 16; } - while (f > 2) { ++result; f /= 2; } - return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f); -} - -static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, - const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) -{ - /* - For PNG filter method 0 - out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are - the scanlines with 1 extra byte per scanline - */ - - unsigned bpp = lodepng_get_bpp(info); - /*the width of a scanline in bytes, not including the filter type*/ - size_t linebytes = (w * bpp + 7) / 8; - /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ - size_t bytewidth = (bpp + 7) / 8; - const unsigned char* prevline = 0; - unsigned x, y; - unsigned error = 0; - LodePNGFilterStrategy strategy = settings->filter_strategy; - - /* - There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: - * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. - use fixed filtering, with the filter None). - * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is - not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply - all five filters and select the filter that produces the smallest sum of absolute values per row. - This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. - - If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, - but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum - heuristic is used. - */ - if (settings->filter_palette_zero && - (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO; - - if (bpp == 0) return 31; /*error: invalid color type*/ - - if (strategy == LFS_ZERO) - { - for (y = 0; y != h; ++y) - { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - out[outindex] = 0; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0); - prevline = &in[inindex]; - } - } - else if (strategy == LFS_MINSUM) - { - /*adaptive filtering*/ - size_t sum[5]; - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned char type, bestType = 0; - - for (type = 0; type != 5; ++type) - { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if (!attempt[type]) return 83; /*alloc fail*/ - } - - if (!error) - { - for (y = 0; y != h; ++y) - { - /*try the 5 filter types*/ - for (type = 0; type != 5; ++type) - { - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - - /*calculate the sum of the result*/ - sum[type] = 0; - if (type == 0) - { - for (x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]); - } - else - { - for (x = 0; x != linebytes; ++x) - { - /*For differences, each byte should be treated as signed, values above 127 are negative - (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. - This means filtertype 0 is almost never chosen, but that is justified.*/ - unsigned char s = attempt[type][x]; - sum[type] += s < 128 ? s : (255U - s); - } - } - - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if (type == 0 || sum[type] < smallest) - { - bestType = type; - smallest = sum[type]; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for (x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - } - - for (type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } - else if (strategy == LFS_ENTROPY) - { - float sum[5]; - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - float smallest = 0; - unsigned type, bestType = 0; - unsigned count[256]; - - for (type = 0; type != 5; ++type) - { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if (!attempt[type]) return 83; /*alloc fail*/ - } - - for (y = 0; y != h; ++y) - { - /*try the 5 filter types*/ - for (type = 0; type != 5; ++type) - { - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - for (x = 0; x != 256; ++x) count[x] = 0; - for (x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; - ++count[type]; /*the filter type itself is part of the scanline*/ - sum[type] = 0; - for (x = 0; x != 256; ++x) - { - float p = count[x] / (float)(linebytes + 1); - sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p; - } - /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ - if (type == 0 || sum[type] < smallest) - { - bestType = type; - smallest = sum[type]; - } - } - - prevline = &in[y * linebytes]; - - /*now fill the out values*/ - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for (x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - - for (type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } - else if (strategy == LFS_PREDEFINED) - { - for (y = 0; y != h; ++y) - { - size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ - size_t inindex = linebytes * y; - unsigned char type = settings->predefined_filters[y]; - out[outindex] = type; /*filter type byte*/ - filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); - prevline = &in[inindex]; - } - } - else if (strategy == LFS_BRUTE_FORCE) - { - /*brute force filter chooser. - deflate the scanline after every filter attempt to see which one deflates best. - This is very slow and gives only slightly smaller, sometimes even larger, result*/ - size_t size[5]; - unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ - size_t smallest = 0; - unsigned type = 0, bestType = 0; - unsigned char* dummy; - LodePNGCompressSettings zlibsettings = settings->zlibsettings; - /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, - to simulate the true case where the tree is the same for the whole image. Sometimes it gives - better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare - cases better compression. It does make this a bit less slow, so it's worth doing this.*/ - zlibsettings.btype = 1; - /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG - images only, so disable it*/ - zlibsettings.custom_zlib = 0; - zlibsettings.custom_deflate = 0; - for (type = 0; type != 5; ++type) - { - attempt[type] = (unsigned char*)lodepng_malloc(linebytes); - if (!attempt[type]) return 83; /*alloc fail*/ - } - for (y = 0; y != h; ++y) /*try the 5 filter types*/ - { - for (type = 0; type != 5; ++type) - { - unsigned testsize = linebytes; - /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ - - filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); - size[type] = 0; - dummy = 0; - zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); - lodepng_free(dummy); - /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ - if (type == 0 || size[type] < smallest) - { - bestType = type; - smallest = size[type]; - } - } - prevline = &in[y * linebytes]; - out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ - for (x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; - } - for (type = 0; type != 5; ++type) lodepng_free(attempt[type]); - } - else return 88; /* unknown filter strategy */ - - return error; -} - -static void addPaddingBits(unsigned char* out, const unsigned char* in, - size_t olinebits, size_t ilinebits, unsigned h) -{ - /*The opposite of the removePaddingBits function - olinebits must be >= ilinebits*/ - unsigned y; - size_t diff = olinebits - ilinebits; - size_t obp = 0, ibp = 0; /*bit pointers*/ - for (y = 0; y != h; ++y) - { - size_t x; - for (x = 0; x < ilinebits; ++x) - { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - /*obp += diff; --> no, fill in some value in the padding bits too, to avoid - "Use of uninitialised value of size ###" warning from valgrind*/ - for (x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); - } -} - -/* -in: non-interlaced image with size w*h -out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with - no padding bits between scanlines, but between reduced images so that each - reduced image starts at a byte. -bpp: bits per pixel -there are no padding bits, not between scanlines, not between reduced images -in has the following size in bits: w * h * bpp. -out is possibly bigger due to padding bits between reduced images -NOTE: comments about padding bits are only relevant if bpp < 8 -*/ -static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) -{ - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned i; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - if (bpp >= 8) - { - for (i = 0; i != 7; ++i) - { - unsigned x, y, b; - size_t bytewidth = bpp / 8; - for (y = 0; y < passh[i]; ++y) - for (x = 0; x < passw[i]; ++x) - { - size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; - size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; - for (b = 0; b < bytewidth; ++b) - { - out[pixeloutstart + b] = in[pixelinstart + b]; - } - } - } - } - else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ - { - for (i = 0; i != 7; ++i) - { - unsigned x, y, b; - unsigned ilinebits = bpp * passw[i]; - unsigned olinebits = bpp * w; - size_t obp, ibp; /*bit pointers (for out and in buffer)*/ - for (y = 0; y < passh[i]; ++y) - for (x = 0; x < passw[i]; ++x) - { - ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; - obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); - for (b = 0; b < bpp; ++b) - { - unsigned char bit = readBitFromReversedStream(&ibp, in); - setBitOfReversedStream(&obp, out, bit); - } - } - } - } -} - -/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. -return value is error**/ -static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, - unsigned w, unsigned h, - const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) -{ - /* - This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: - *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter - *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter - */ - unsigned bpp = lodepng_get_bpp(&info_png->color); - unsigned error = 0; - - if (info_png->interlace_method == 0) - { - *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)lodepng_malloc(*outsize); - if (!(*out) && (*outsize)) error = 83; /*alloc fail*/ - - if (!error) - { - /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ - if (bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) - { - unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8)); - if (!padded) error = 83; /*alloc fail*/ - if (!error) - { - addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h); - error = filter(*out, padded, w, h, &info_png->color, settings); - } - lodepng_free(padded); - } - else - { - /*we can immediately filter into the out buffer, no other steps needed*/ - error = filter(*out, in, w, h, &info_png->color, settings); - } - } - } - else /*interlace_method is 1 (Adam7)*/ - { - unsigned passw[7], passh[7]; - size_t filter_passstart[8], padded_passstart[8], passstart[8]; - unsigned char* adam7; - - Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); - - *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ - *out = (unsigned char*)lodepng_malloc(*outsize); - if (!(*out)) error = 83; /*alloc fail*/ - - adam7 = (unsigned char*)lodepng_malloc(passstart[7]); - if (!adam7 && passstart[7]) error = 83; /*alloc fail*/ - - if (!error) - { - unsigned i; - - Adam7_interlace(adam7, in, w, h, bpp); - for (i = 0; i != 7; ++i) - { - if (bpp < 8) - { - unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); - if (!padded) ERROR_BREAK(83); /*alloc fail*/ - addPaddingBits(padded, &adam7[passstart[i]], - ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]); - error = filter(&(*out)[filter_passstart[i]], padded, - passw[i], passh[i], &info_png->color, settings); - lodepng_free(padded); - } - else - { - error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], - passw[i], passh[i], &info_png->color, settings); - } - - if (error) break; - } - } - - lodepng_free(adam7); - } - - return error; -} - -/* -palette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA... -returns 0 if the palette is opaque, -returns 1 if the palette has a single color with alpha 0 ==> color key -returns 2 if the palette is semi-translucent. -*/ -static unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize) -{ - size_t i; - unsigned key = 0; - unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/ - for (i = 0; i != palettesize; ++i) - { - if (!key && palette[4 * i + 3] == 0) - { - r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2]; - key = 1; - i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/ - } - else if (palette[4 * i + 3] != 255) return 2; - /*when key, no opaque RGB may have key's RGB*/ - else if (key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2; - } - return key; -} - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) -{ - unsigned char* inchunk = data; - while ((size_t)(inchunk - data) < datasize) - { - CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); - out->allocsize = out->size; /*fix the allocsize again*/ - inchunk = lodepng_chunk_next(inchunk); - } - return 0; -} -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -unsigned lodepng_encode(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGState* state) -{ - LodePNGInfo info; - ucvector outv; - unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ - size_t datasize = 0; - - /*provide some proper output values if error will happen*/ - *out = 0; - *outsize = 0; - state->error = 0; - - lodepng_info_init(&info); - lodepng_info_copy(&info, &state->info_png); - - if ((info.color.colortype == LCT_PALETTE || state->encoder.force_palette) - && (info.color.palettesize == 0 || info.color.palettesize > 256)) - { - state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ - return state->error; - } - - if (state->encoder.auto_convert) - { - state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw); - } - if (state->error) return state->error; - - if (state->encoder.zlibsettings.btype > 2) - { - CERROR_RETURN_ERROR(state->error, 61); /*error: unexisting btype*/ - } - if (state->info_png.interlace_method > 1) - { - CERROR_RETURN_ERROR(state->error, 71); /*error: unexisting interlace mode*/ - } - - state->error = checkColorValidity(info.color.colortype, info.color.bitdepth); - if (state->error) return state->error; /*error: unexisting color type given*/ - state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); - if (state->error) return state->error; /*error: unexisting color type given*/ - - if (!lodepng_color_mode_equal(&state->info_raw, &info.color)) - { - unsigned char* converted; - size_t size = (w * h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8; - - converted = (unsigned char*)lodepng_malloc(size); - if (!converted && size) state->error = 83; /*alloc fail*/ - if (!state->error) - { - state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); - } - if (!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); - lodepng_free(converted); - } - else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); - - ucvector_init(&outv); - while (!state->error) /*while only executed once, to break on error*/ - { -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - size_t i; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*write signature and chunks*/ - writeSignature(&outv); - /*IHDR*/ - addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*unknown chunks between IHDR and PLTE*/ - if (info.unknown_chunks_data[0]) - { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); - if (state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*PLTE*/ - if (info.color.colortype == LCT_PALETTE) - { - addChunk_PLTE(&outv, &info.color); - } - if (state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) - { - addChunk_PLTE(&outv, &info.color); - } - /*tRNS*/ - if (info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0) - { - addChunk_tRNS(&outv, &info.color); - } - if ((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined) - { - addChunk_tRNS(&outv, &info.color); - } -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*bKGD (must come between PLTE and the IDAt chunks*/ - if (info.background_defined) addChunk_bKGD(&outv, &info); - /*pHYs (must come before the IDAT chunks)*/ - if (info.phys_defined) addChunk_pHYs(&outv, &info); - - /*unknown chunks between PLTE and IDAT*/ - if (info.unknown_chunks_data[1]) - { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); - if (state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - /*IDAT (multiple IDAT chunks must be consecutive)*/ - state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); - if (state->error) break; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*tIME*/ - if (info.time_defined) addChunk_tIME(&outv, &info.time); - /*tEXt and/or zTXt*/ - for (i = 0; i != info.text_num; ++i) - { - if (strlen(info.text_keys[i]) > 79) - { - state->error = 66; /*text chunk too large*/ - break; - } - if (strlen(info.text_keys[i]) < 1) - { - state->error = 67; /*text chunk too small*/ - break; - } - if (state->encoder.text_compression) - { - addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); - } - else - { - addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); - } - } - /*LodePNG version id in text chunk*/ - if (state->encoder.add_id) - { - unsigned alread_added_id_text = 0; - for (i = 0; i != info.text_num; ++i) - { - if (!strcmp(info.text_keys[i], "LodePNG")) - { - alread_added_id_text = 1; - break; - } - } - if (alread_added_id_text == 0) - { - addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ - } - } - /*iTXt*/ - for (i = 0; i != info.itext_num; ++i) - { - if (strlen(info.itext_keys[i]) > 79) - { - state->error = 66; /*text chunk too large*/ - break; - } - if (strlen(info.itext_keys[i]) < 1) - { - state->error = 67; /*text chunk too small*/ - break; - } - addChunk_iTXt(&outv, state->encoder.text_compression, - info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], - &state->encoder.zlibsettings); - } - - /*unknown chunks between IDAT and IEND*/ - if (info.unknown_chunks_data[2]) - { - state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); - if (state->error) break; - } -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - addChunk_IEND(&outv); - - break; /*this isn't really a while loop; no error happened so break out now!*/ - } - - lodepng_info_cleanup(&info); - lodepng_free(data); - /*instead of cleaning the vector up, give it to the output*/ - *out = outv.data; - *outsize = outv.size; - - return state->error; -} - -unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, - unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) -{ - unsigned error; - LodePNGState state; - lodepng_state_init(&state); - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - state.info_png.color.colortype = colortype; - state.info_png.color.bitdepth = bitdepth; - lodepng_encode(out, outsize, image, w, h, &state); - error = state.error; - lodepng_state_cleanup(&state); - return error; -} - -unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) -{ - return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); -} - -unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) -{ - return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); -} - -#ifdef LODEPNG_COMPILE_DISK -unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) -{ - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); - if (!error) error = lodepng_save_file(buffer, buffersize, filename); - lodepng_free(buffer); - return error; -} - -unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) -{ - return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); -} - -unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) -{ - return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); -} -#endif /*LODEPNG_COMPILE_DISK*/ - -void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) -{ - lodepng_compress_settings_init(&settings->zlibsettings); - settings->filter_palette_zero = 1; - settings->filter_strategy = LFS_MINSUM; - settings->auto_convert = 1; - settings->force_palette = 0; - settings->predefined_filters = 0; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - settings->add_id = 0; - settings->text_compression = 1; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} - -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ERROR_TEXT -/* -This returns the description of a numerical error code in English. This is also -the documentation of all the error codes. -*/ -const char* lodepng_error_text(unsigned code) -{ - switch (code) - { - case 0: return "no error, everything went ok"; - case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ - case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ - case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ - case 13: return "problem while processing dynamic deflate block"; - case 14: return "problem while processing dynamic deflate block"; - case 15: return "problem while processing dynamic deflate block"; - case 16: return "unexisting code while processing dynamic deflate block"; - case 17: return "end of out buffer memory reached while inflating"; - case 18: return "invalid distance code while inflating"; - case 19: return "end of out buffer memory reached while inflating"; - case 20: return "invalid deflate block BTYPE encountered while decoding"; - case 21: return "NLEN is not ones complement of LEN in a deflate block"; - /*end of out buffer memory reached while inflating: - This can happen if the inflated deflate data is longer than the amount of bytes required to fill up - all the pixels of the image, given the color depth and image dimensions. Something that doesn't - happen in a normal, well encoded, PNG image.*/ - case 22: return "end of out buffer memory reached while inflating"; - case 23: return "end of in buffer memory reached while inflating"; - case 24: return "invalid FCHECK in zlib header"; - case 25: return "invalid compression method in zlib header"; - case 26: return "FDICT encountered in zlib header while it's not used for PNG"; - case 27: return "PNG file is smaller than a PNG header"; - /*Checks the magic file header, the first 8 bytes of the PNG file*/ - case 28: return "incorrect PNG signature, it's no PNG or corrupted"; - case 29: return "first chunk is not the header chunk"; - case 30: return "chunk length too large, chunk broken off at end of file"; - case 31: return "illegal PNG color type or bpp"; - case 32: return "illegal PNG compression method"; - case 33: return "illegal PNG filter method"; - case 34: return "illegal PNG interlace method"; - case 35: return "chunk length of a chunk is too large or the chunk too small"; - case 36: return "illegal PNG filter type encountered"; - case 37: return "illegal bit depth for this color type given"; - case 38: return "the palette is too big"; /*more than 256 colors*/ - case 39: return "more palette alpha values given in tRNS chunk than there are colors in the palette"; - case 40: return "tRNS chunk has wrong size for greyscale image"; - case 41: return "tRNS chunk has wrong size for RGB image"; - case 42: return "tRNS chunk appeared while it was not allowed for this color type"; - case 43: return "bKGD chunk has wrong size for palette image"; - case 44: return "bKGD chunk has wrong size for greyscale image"; - case 45: return "bKGD chunk has wrong size for RGB image"; - case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; - case 49: return "jumped past memory while generating dynamic huffman tree"; - case 50: return "jumped past memory while generating dynamic huffman tree"; - case 51: return "jumped past memory while inflating huffman block"; - case 52: return "jumped past memory while inflating"; - case 53: return "size of zlib data too small"; - case 54: return "repeat symbol in tree while there was no value symbol yet"; - /*jumped past tree while generating huffman tree, this could be when the - tree will have more leaves than symbols after generating it out of the - given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ - case 55: return "jumped past tree while generating huffman tree"; - case 56: return "given output image colortype or bitdepth not supported for color conversion"; - case 57: return "invalid CRC encountered (checking CRC can be disabled)"; - case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; - case 59: return "requested color conversion not supported"; - case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; - case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; - /*LodePNG leaves the choice of RGB to greyscale conversion formula to the user.*/ - case 62: return "conversion from color to greyscale not supported"; - case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; /*(2^31-1)*/ - /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ - case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; - case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; - case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; - case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; - case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; - case 71: return "unexisting interlace mode given to encoder (must be 0 or 1)"; - case 72: return "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)"; - case 73: return "invalid tIME chunk size"; - case 74: return "invalid pHYs chunk size"; - /*length could be wrong, or data chopped off*/ - case 75: return "no null termination char found while decoding text chunk"; - case 76: return "iTXt chunk too short to contain required bytes"; - case 77: return "integer overflow in buffer size"; - case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ - case 79: return "failed to open file for writing"; - case 80: return "tried creating a tree of 0 symbols"; - case 81: return "lazy matching at pos 0 is impossible"; - case 82: return "color conversion to palette requested while a color isn't in palette"; - case 83: return "memory allocation failed"; - case 84: return "given image too small to contain all pixels to be encoded"; - case 86: return "impossible offset in lz77 encoding (internal bug)"; - case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; - case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; - case 89: return "text chunk keyword too short or long: must have size 1-79"; - /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ - case 90: return "windowsize must be a power of two"; - case 91: return "invalid decompressed idat size"; - case 92: return "too many pixels, not supported"; - case 93: return "zero width or height is invalid"; - case 94: return "header chunk must have a size of 13 bytes"; - } - return "unknown error code"; -} -#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ - -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* // C++ Wrapper // */ -/* ////////////////////////////////////////////////////////////////////////// */ -/* ////////////////////////////////////////////////////////////////////////// */ - -#ifdef LODEPNG_COMPILE_CPP -namespace lodepng -{ - -#ifdef LODEPNG_COMPILE_DISK - unsigned load_file(std::vector& buffer, const std::string& filename) - { - long size = lodepng_filesize(filename.c_str()); - if (size < 0) return 78; - buffer.resize((size_t)size); - return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); - } - - /*write given buffer to the file, overwriting the file, it doesn't append to it.*/ - unsigned save_file(const std::vector& buffer, const std::string& filename) - { - return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); - } -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_DECODER - unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings& settings) - { - unsigned char* buffer = 0; - size_t buffersize = 0; - unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings); - if (buffer) - { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; - } - - unsigned decompress(std::vector& out, const std::vector& in, - const LodePNGDecompressSettings& settings) - { - return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); - } -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER - unsigned compress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings& settings) - { - unsigned char* buffer = 0; - size_t buffersize = 0; - unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); - if (buffer) - { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; - } - - unsigned compress(std::vector& out, const std::vector& in, - const LodePNGCompressSettings& settings) - { - return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); - } -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_ZLIB */ - - -#ifdef LODEPNG_COMPILE_PNG - - State::State() - { - lodepng_state_init(this); - } - - State::State(const State& other) - { - lodepng_state_init(this); - lodepng_state_copy(this, &other); - } - - State::~State() - { - lodepng_state_cleanup(this); - } - - State& State::operator=(const State& other) - { - lodepng_state_copy(this, &other); - return *this; - } - -#ifdef LODEPNG_COMPILE_DECODER - - unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, - size_t insize, LodePNGColorType colortype, unsigned bitdepth) - { - unsigned char* buffer; - unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); - if (buffer && !error) - { - State state; - state.info_raw.colortype = colortype; - state.info_raw.bitdepth = bitdepth; - size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; - } - - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) - { - return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); - } - - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const unsigned char* in, size_t insize) - { - unsigned char* buffer = NULL; - unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); - if (buffer && !error) - { - size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - } - lodepng_free(buffer); - return error; - } - - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const std::vector& in) - { - return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); - } - -#ifdef LODEPNG_COMPILE_DISK - unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, - LodePNGColorType colortype, unsigned bitdepth) - { - std::vector buffer; - unsigned error = load_file(buffer, filename); - if (error) return error; - return decode(out, w, h, buffer, colortype, bitdepth); - } -#endif /* LODEPNG_COMPILE_DECODER */ -#endif /* LODEPNG_COMPILE_DISK */ - -#ifdef LODEPNG_COMPILE_ENCODER - unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) - { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); - if (buffer) - { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; - } - - unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) - { - if (lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; - return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); - } - - unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - State& state) - { - unsigned char* buffer; - size_t buffersize; - unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); - if (buffer) - { - out.insert(out.end(), &buffer[0], &buffer[buffersize]); - lodepng_free(buffer); - } - return error; - } - - unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - State& state) - { - if (lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; - return encode(out, in.empty() ? 0 : &in[0], w, h, state); - } - -#ifdef LODEPNG_COMPILE_DISK - unsigned encode(const std::string& filename, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) - { - std::vector buffer; - unsigned error = encode(buffer, in, w, h, colortype, bitdepth); - if (!error) error = save_file(buffer, filename); - return error; - } - - unsigned encode(const std::string& filename, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth) - { - if (lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; - return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); - } -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_PNG */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ diff --git a/src/rgbcx/test/lodepng.h b/src/rgbcx/test/lodepng.h deleted file mode 100644 index df0f1e7..0000000 --- a/src/rgbcx/test/lodepng.h +++ /dev/null @@ -1,1761 +0,0 @@ -/* -LodePNG version 20161127 - -Copyright (c) 2005-2016 Lode Vandevenne - -This software is provided 'as-is', without any express or implied -warranty. In no event will the authors be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - - 3. This notice may not be removed or altered from any source - distribution. -*/ - -#ifndef LODEPNG_H -#define LODEPNG_H - -#include /*for size_t*/ - -extern const char* LODEPNG_VERSION_STRING; - -/* -The following #defines are used to create code sections. They can be disabled -to disable code sections, which can give faster compile time and smaller binary. -The "NO_COMPILE" defines are designed to be used to pass as defines to the -compiler command to disable them without modifying this header, e.g. --DLODEPNG_NO_COMPILE_ZLIB for gcc. -In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to -allow implementing a custom lodepng_crc32. -*/ -/*deflate & zlib. If disabled, you must specify alternative zlib functions in -the custom_zlib field of the compress and decompress settings*/ -#ifndef LODEPNG_NO_COMPILE_ZLIB -#define LODEPNG_COMPILE_ZLIB -#endif -/*png encoder and png decoder*/ -#ifndef LODEPNG_NO_COMPILE_PNG -#define LODEPNG_COMPILE_PNG -#endif -/*deflate&zlib decoder and png decoder*/ -#ifndef LODEPNG_NO_COMPILE_DECODER -#define LODEPNG_COMPILE_DECODER -#endif -/*deflate&zlib encoder and png encoder*/ -#ifndef LODEPNG_NO_COMPILE_ENCODER -#define LODEPNG_COMPILE_ENCODER -#endif -/*the optional built in harddisk file loading and saving functions*/ -#ifndef LODEPNG_NO_COMPILE_DISK -#define LODEPNG_COMPILE_DISK -#endif -/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ -#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS -#define LODEPNG_COMPILE_ANCILLARY_CHUNKS -#endif -/*ability to convert error numerical codes to English text string*/ -#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT -#define LODEPNG_COMPILE_ERROR_TEXT -#endif -/*Compile the default allocators (C's free, malloc and realloc). If you disable this, -you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your -source files with custom allocators.*/ -#ifndef LODEPNG_NO_COMPILE_ALLOCATORS -#define LODEPNG_COMPILE_ALLOCATORS -#endif -/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ -#ifdef __cplusplus -#ifndef LODEPNG_NO_COMPILE_CPP -#define LODEPNG_COMPILE_CPP -#endif -#endif - -#ifdef LODEPNG_COMPILE_CPP -#include -#include -#endif /*LODEPNG_COMPILE_CPP*/ - -#ifdef LODEPNG_COMPILE_PNG -/*The PNG color types (also used for raw).*/ -typedef enum LodePNGColorType -{ - LCT_GREY = 0, /*greyscale: 1,2,4,8,16 bit*/ - LCT_RGB = 2, /*RGB: 8,16 bit*/ - LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ - LCT_GREY_ALPHA = 4, /*greyscale with alpha: 8,16 bit*/ - LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/ -} LodePNGColorType; - -#ifdef LODEPNG_COMPILE_DECODER -/* -Converts PNG data in memory to raw pixel data. -out: Output parameter. Pointer to buffer that will contain the raw pixel data. - After decoding, its size is w * h * (bytes per pixel) bytes larger than - initially. Bytes per pixel depends on colortype and bitdepth. - Must be freed after usage with free(*out). - Note: for 16-bit per channel colors, uses big endian format like PNG does. -w: Output parameter. Pointer to width of pixel data. -h: Output parameter. Pointer to height of pixel data. -in: Memory buffer with the PNG file. -insize: size of the in buffer. -colortype: the desired color type for the raw output image. See explanation on PNG color types. -bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. -Return value: LodePNG error code (0 means no error). -*/ -unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ -unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize); - -/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ -unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, - const unsigned char* in, size_t insize); - -#ifdef LODEPNG_COMPILE_DISK -/* -Load PNG from disk, from file with given name. -Same as the other decode functions, but instead takes a filename as input. -*/ -unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/ -unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename); - -/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/ -unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, - const char* filename); -#endif /*LODEPNG_COMPILE_DISK*/ -#endif /*LODEPNG_COMPILE_DECODER*/ - - -#ifdef LODEPNG_COMPILE_ENCODER -/* -Converts raw pixel data into a PNG image in memory. The colortype and bitdepth - of the output PNG image cannot be chosen, they are automatically determined - by the colortype, bitdepth and content of the input pixel data. - Note: for 16-bit per channel colors, needs big endian format like PNG does. -out: Output parameter. Pointer to buffer that will contain the PNG image data. - Must be freed after usage with free(*out). -outsize: Output parameter. Pointer to the size in bytes of the out buffer. -image: The raw pixel data to encode. The size of this buffer should be - w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. -w: width of the raw pixel data in pixels. -h: height of the raw pixel data in pixels. -colortype: the color type of the raw input image. See explanation on PNG color types. -bitdepth: the bit depth of the raw input image. See explanation on PNG color types. -Return value: LodePNG error code (0 means no error). -*/ -unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ -unsigned lodepng_encode32(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h); - -/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ -unsigned lodepng_encode24(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h); - -#ifdef LODEPNG_COMPILE_DISK -/* -Converts raw pixel data into a PNG file on disk. -Same as the other encode functions, but instead takes a filename as output. -NOTE: This overwrites existing files without warning! -*/ -unsigned lodepng_encode_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h, - LodePNGColorType colortype, unsigned bitdepth); - -/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/ -unsigned lodepng_encode32_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h); - -/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/ -unsigned lodepng_encode24_file(const char* filename, - const unsigned char* image, unsigned w, unsigned h); -#endif /*LODEPNG_COMPILE_DISK*/ -#endif /*LODEPNG_COMPILE_ENCODER*/ - - -#ifdef LODEPNG_COMPILE_CPP -namespace lodepng -{ -#ifdef LODEPNG_COMPILE_DECODER - /*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype - is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const unsigned char* in, size_t insize, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::vector& in, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#ifdef LODEPNG_COMPILE_DISK - /* - Converts PNG file from disk to raw pixel data in memory. - Same as the other decode functions, but instead takes a filename as input. - */ - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - const std::string& filename, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER - /*Same as lodepng_encode_memory, but encodes to an std::vector. colortype - is that of the raw input data. The output PNG color type will be auto chosen.*/ - unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); - unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#ifdef LODEPNG_COMPILE_DISK - /* - Converts 32-bit RGBA raw pixel data into a PNG file on disk. - Same as the other encode functions, but instead takes a filename as output. - NOTE: This overwrites existing files without warning! - */ - unsigned encode(const std::string& filename, - const unsigned char* in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); - unsigned encode(const std::string& filename, - const std::vector& in, unsigned w, unsigned h, - LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_ENCODER */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ -#endif /*LODEPNG_COMPILE_PNG*/ - -#ifdef LODEPNG_COMPILE_ERROR_TEXT -/*Returns an English description of the numerical error code.*/ -const char* lodepng_error_text(unsigned code); -#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ - -#ifdef LODEPNG_COMPILE_DECODER -/*Settings for zlib decompression*/ -typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; -struct LodePNGDecompressSettings -{ - unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ - - /*use custom zlib decoder instead of built in one (default: null)*/ - unsigned(*custom_zlib)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGDecompressSettings*); - /*use custom deflate decoder instead of built in one (default: null) - if custom_zlib is used, custom_deflate is ignored since only the built in - zlib function will call custom_deflate*/ - unsigned(*custom_inflate)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGDecompressSettings*); - - const void* custom_context; /*optional custom settings for custom functions*/ -}; - -extern const LodePNGDecompressSettings lodepng_default_decompress_settings; -void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/* -Settings for zlib compression. Tweaking these settings tweaks the balance -between speed and compression ratio. -*/ -typedef struct LodePNGCompressSettings LodePNGCompressSettings; -struct LodePNGCompressSettings /*deflate = compress*/ -{ - /*LZ77 related settings*/ - unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ - unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ - unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ - unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ - unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ - unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ - - /*use custom zlib encoder instead of built in one (default: null)*/ - unsigned(*custom_zlib)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGCompressSettings*); - /*use custom deflate encoder instead of built in one (default: null) - if custom_zlib is used, custom_deflate is ignored since only the built in - zlib function will call custom_deflate*/ - unsigned(*custom_deflate)(unsigned char**, size_t*, - const unsigned char*, size_t, - const LodePNGCompressSettings*); - - const void* custom_context; /*optional custom settings for custom functions*/ -}; - -extern const LodePNGCompressSettings lodepng_default_compress_settings; -void lodepng_compress_settings_init(LodePNGCompressSettings* settings); -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_PNG -/* -Color mode of an image. Contains all information required to decode the pixel -bits to RGBA colors. This information is the same as used in the PNG file -format, and is used both for PNG and raw image data in LodePNG. -*/ -typedef struct LodePNGColorMode -{ - /*header (IHDR)*/ - LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ - unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ - - /* - palette (PLTE and tRNS) - - Dynamically allocated with the colors of the palette, including alpha. - When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use - lodepng_palette_clear, then for each color use lodepng_palette_add. - If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette. - - When decoding, by default you can ignore this palette, since LodePNG already - fills the palette colors in the pixels of the raw RGBA output. - - The palette is only supported for color type 3. - */ - unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/ - size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/ - - /* - transparent color key (tRNS) - - This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. - For greyscale PNGs, r, g and b will all 3 be set to the same. - - When decoding, by default you can ignore this information, since LodePNG sets - pixels with this key to transparent already in the raw RGBA output. - - The color key is only supported for color types 0 and 2. - */ - unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ - unsigned key_r; /*red/greyscale component of color key*/ - unsigned key_g; /*green component of color key*/ - unsigned key_b; /*blue component of color key*/ -} LodePNGColorMode; - -/*init, cleanup and copy functions to use with this struct*/ -void lodepng_color_mode_init(LodePNGColorMode* info); -void lodepng_color_mode_cleanup(LodePNGColorMode* info); -/*return value is error code (0 means no error)*/ -unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); - -void lodepng_palette_clear(LodePNGColorMode* info); -/*add 1 color to the palette*/ -unsigned lodepng_palette_add(LodePNGColorMode* info, - unsigned char r, unsigned char g, unsigned char b, unsigned char a); - -/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ -unsigned lodepng_get_bpp(const LodePNGColorMode* info); -/*get the amount of color channels used, based on colortype in the struct. -If a palette is used, it counts as 1 channel.*/ -unsigned lodepng_get_channels(const LodePNGColorMode* info); -/*is it a greyscale type? (only colortype 0 or 4)*/ -unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); -/*has it got an alpha channel? (only colortype 2 or 6)*/ -unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); -/*has it got a palette? (only colortype 3)*/ -unsigned lodepng_is_palette_type(const LodePNGColorMode* info); -/*only returns true if there is a palette and there is a value in the palette with alpha < 255. -Loops through the palette to check this.*/ -unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); -/* -Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. -Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). -Returns false if the image can only have opaque pixels. -In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, -or if "key_defined" is true. -*/ -unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); -/*Returns the byte size of a raw image buffer with given width, height and color mode*/ -size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -/*The information of a Time chunk in PNG.*/ -typedef struct LodePNGTime -{ - unsigned year; /*2 bytes used (0-65535)*/ - unsigned month; /*1-12*/ - unsigned day; /*1-31*/ - unsigned hour; /*0-23*/ - unsigned minute; /*0-59*/ - unsigned second; /*0-60 (to allow for leap seconds)*/ -} LodePNGTime; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/*Information about the PNG image, except pixels, width and height.*/ -typedef struct LodePNGInfo -{ - /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ - unsigned compression_method;/*compression method of the original file. Always 0.*/ - unsigned filter_method; /*filter method of the original file*/ - unsigned interlace_method; /*interlace method of the original file*/ - LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /* - suggested background color chunk (bKGD) - This color uses the same color mode as the PNG (except alpha channel), which can be 1-bit to 16-bit. - - For greyscale PNGs, r, g and b will all 3 be set to the same. When encoding - the encoder writes the red one. For palette PNGs: When decoding, the RGB value - will be stored, not a palette index. But when encoding, specify the index of - the palette in background_r, the other two are then ignored. - - The decoder does not use this background color to edit the color of pixels. - */ - unsigned background_defined; /*is a suggested background color given?*/ - unsigned background_r; /*red component of suggested background color*/ - unsigned background_g; /*green component of suggested background color*/ - unsigned background_b; /*blue component of suggested background color*/ - - /* - non-international text chunks (tEXt and zTXt) - - The char** arrays each contain num strings. The actual messages are in - text_strings, while text_keys are keywords that give a short description what - the actual text represents, e.g. Title, Author, Description, or anything else. - - A keyword is minimum 1 character and maximum 79 characters long. It's - discouraged to use a single line length longer than 79 characters for texts. - - Don't allocate these text buffers yourself. Use the init/cleanup functions - correctly and use lodepng_add_text and lodepng_clear_text. - */ - size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ - char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ - char** text_strings; /*the actual text*/ - - /* - international text chunks (iTXt) - Similar to the non-international text chunks, but with additional strings - "langtags" and "transkeys". - */ - size_t itext_num; /*the amount of international texts in this PNG*/ - char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ - char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ - char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ - char** itext_strings; /*the actual international text - UTF-8 string*/ - - /*time chunk (tIME)*/ - unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ - LodePNGTime time; - - /*phys chunk (pHYs)*/ - unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ - unsigned phys_x; /*pixels per unit in x direction*/ - unsigned phys_y; /*pixels per unit in y direction*/ - unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ - - /* - unknown chunks - There are 3 buffers, one for each position in the PNG where unknown chunks can appear - each buffer contains all unknown chunks for that position consecutively - The 3 buffers are the unknown chunks between certain critical chunks: - 0: IHDR-PLTE, 1: PLTE-IDAT, 2: IDAT-IEND - Do not allocate or traverse this data yourself. Use the chunk traversing functions declared - later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. - */ - unsigned char* unknown_chunks_data[3]; - size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} LodePNGInfo; - -/*init, cleanup and copy functions to use with this struct*/ -void lodepng_info_init(LodePNGInfo* info); -void lodepng_info_cleanup(LodePNGInfo* info); -/*return value is error code (0 means no error)*/ -unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS -void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ -unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ - -void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ -unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, - const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ - -/* -Converts raw buffer from one color type to another color type, based on -LodePNGColorMode structs to describe the input and output color type. -See the reference manual at the end of this header file to see which color conversions are supported. -return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) -The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel -of the output color type (lodepng_get_bpp). -For < 8 bpp images, there should not be padding bits at the end of scanlines. -For 16-bit per channel colors, uses big endian format like PNG does. -Return value is LodePNG error code -*/ -unsigned lodepng_convert(unsigned char* out, const unsigned char* in, - const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, - unsigned w, unsigned h); - -#ifdef LODEPNG_COMPILE_DECODER -/* -Settings for the decoder. This contains settings for the PNG and the Zlib -decoder, but not the Info settings from the Info structs. -*/ -typedef struct LodePNGDecoderSettings -{ - LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ - - unsigned ignore_crc; /*ignore CRC checksums*/ - - unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ - -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ - /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ - unsigned remember_unknown_chunks; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} LodePNGDecoderSettings; - -void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ -typedef enum LodePNGFilterStrategy -{ - /*every filter at zero*/ - LFS_ZERO, - /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ - LFS_MINSUM, - /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending - on the image, this is better or worse than minsum.*/ - LFS_ENTROPY, - /* - Brute-force-search PNG filters by compressing each filter for each scanline. - Experimental, very slow, and only rarely gives better compression than MINSUM. - */ - LFS_BRUTE_FORCE, - /*use predefined_filters buffer: you specify the filter type for each scanline*/ - LFS_PREDEFINED -} LodePNGFilterStrategy; - -/*Gives characteristics about the colors of the image, which helps decide which color model to use for encoding. -Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms.*/ -typedef struct LodePNGColorProfile -{ - unsigned colored; /*not greyscale*/ - unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ - unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ - unsigned short key_g; - unsigned short key_b; - unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ - unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/ - unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/ - unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/ -} LodePNGColorProfile; - -void lodepng_color_profile_init(LodePNGColorProfile* profile); - -/*Get a LodePNGColorProfile of the image.*/ -unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, - const unsigned char* image, unsigned w, unsigned h, - const LodePNGColorMode* mode_in); -/*The function LodePNG uses internally to decide the PNG color with auto_convert. -Chooses an optimal color model, e.g. grey if only grey pixels, palette if < 256 colors, ...*/ -unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, - const unsigned char* image, unsigned w, unsigned h, - const LodePNGColorMode* mode_in); - -/*Settings for the encoder.*/ -typedef struct LodePNGEncoderSettings -{ - LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ - - unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ - - /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than - 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to - completely follow the official PNG heuristic, filter_palette_zero must be true and - filter_strategy must be LFS_MINSUM*/ - unsigned filter_palette_zero; - /*Which filter strategy to use when not using zeroes due to filter_palette_zero. - Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ - LodePNGFilterStrategy filter_strategy; - /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with - the same length as the amount of scanlines in the image, and each value must <= 5. You - have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero - must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ - const unsigned char* predefined_filters; - - /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). - If colortype is 3, PLTE is _always_ created.*/ - unsigned force_palette; -#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS - /*add LodePNG identifier and version as a text chunk, for debugging*/ - unsigned add_id; - /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ - unsigned text_compression; -#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ -} LodePNGEncoderSettings; - -void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); -#endif /*LODEPNG_COMPILE_ENCODER*/ - - -#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) -/*The settings, state and information for extended encoding and decoding.*/ -typedef struct LodePNGState -{ -#ifdef LODEPNG_COMPILE_DECODER - LodePNGDecoderSettings decoder; /*the decoding settings*/ -#endif /*LODEPNG_COMPILE_DECODER*/ -#ifdef LODEPNG_COMPILE_ENCODER - LodePNGEncoderSettings encoder; /*the encoding settings*/ -#endif /*LODEPNG_COMPILE_ENCODER*/ - LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ - LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ - unsigned error; -#ifdef LODEPNG_COMPILE_CPP - /* For the lodepng::State subclass. */ - virtual ~LodePNGState() {} -#endif -} LodePNGState; - -/*init, cleanup and copy functions to use with this struct*/ -void lodepng_state_init(LodePNGState* state); -void lodepng_state_cleanup(LodePNGState* state); -void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); -#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ - -#ifdef LODEPNG_COMPILE_DECODER -/* -Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and -getting much more information about the PNG image and color mode. -*/ -unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize); - -/* -Read the PNG header, but not the actual data. This returns only the information -that is in the header chunk of the PNG, such as width, height and color type. The -information is placed in the info_png field of the LodePNGState. -*/ -unsigned lodepng_inspect(unsigned* w, unsigned* h, - LodePNGState* state, - const unsigned char* in, size_t insize); -#endif /*LODEPNG_COMPILE_DECODER*/ - - -#ifdef LODEPNG_COMPILE_ENCODER -/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ -unsigned lodepng_encode(unsigned char** out, size_t* outsize, - const unsigned char* image, unsigned w, unsigned h, - LodePNGState* state); -#endif /*LODEPNG_COMPILE_ENCODER*/ - -/* -The lodepng_chunk functions are normally not needed, except to traverse the -unknown chunks stored in the LodePNGInfo struct, or add new ones to it. -It also allows traversing the chunks of an encoded PNG file yourself. - -PNG standard chunk naming conventions: -First byte: uppercase = critical, lowercase = ancillary -Second byte: uppercase = public, lowercase = private -Third byte: must be uppercase -Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy -*/ - -/* -Gets the length of the data of the chunk. Total chunk length has 12 bytes more. -There must be at least 4 bytes to read from. If the result value is too large, -it may be corrupt data. -*/ -unsigned lodepng_chunk_length(const unsigned char* chunk); - -/*puts the 4-byte type in null terminated string*/ -void lodepng_chunk_type(char type[5], const unsigned char* chunk); - -/*check if the type is the given type*/ -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); - -/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ -unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); - -/*0: public, 1: private (see PNG standard)*/ -unsigned char lodepng_chunk_private(const unsigned char* chunk); - -/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); - -/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ -unsigned char* lodepng_chunk_data(unsigned char* chunk); -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); - -/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ -unsigned lodepng_chunk_check_crc(const unsigned char* chunk); - -/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ -void lodepng_chunk_generate_crc(unsigned char* chunk); - -/*iterate to next chunks. don't use on IEND chunk, as there is no next chunk then*/ -unsigned char* lodepng_chunk_next(unsigned char* chunk); -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk); - -/* -Appends chunk to the data in out. The given chunk should already have its chunk header. -The out variable and outlength are updated to reflect the new reallocated buffer. -Returns error code (0 if it went ok) -*/ -unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk); - -/* -Appends new chunk to out. The chunk to append is given by giving its length, type -and data separately. The type is a 4-letter string. -The out variable and outlength are updated to reflect the new reallocated buffer. -Returne error code (0 if it went ok) -*/ -unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, - const char* type, const unsigned char* data); - - -/*Calculate CRC32 of buffer*/ -unsigned lodepng_crc32(const unsigned char* buf, size_t len); -#endif /*LODEPNG_COMPILE_PNG*/ - - -#ifdef LODEPNG_COMPILE_ZLIB -/* -This zlib part can be used independently to zlib compress and decompress a -buffer. It cannot be used to create gzip files however, and it only supports the -part of zlib that is required for PNG, it does not support dictionaries. -*/ - -#ifdef LODEPNG_COMPILE_DECODER -/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ -unsigned lodepng_inflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings); - -/* -Decompresses Zlib data. Reallocates the out buffer and appends the data. The -data must be according to the zlib specification. -Either, *out must be NULL and *outsize must be 0, or, *out must be a valid -buffer and *outsize its size in bytes. out must be freed by user after usage. -*/ -unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGDecompressSettings* settings); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER -/* -Compresses data with Zlib. Reallocates the out buffer and appends the data. -Zlib adds a small header and trailer around the deflate data. -The data is output in the format of the zlib specification. -Either, *out must be NULL and *outsize must be 0, or, *out must be a valid -buffer and *outsize its size in bytes. out must be freed by user after usage. -*/ -unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings); - -/* -Find length-limited Huffman code for given frequencies. This function is in the -public interface only for tests, it's used internally by lodepng_deflate. -*/ -unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, - size_t numcodes, unsigned maxbitlen); - -/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ -unsigned lodepng_deflate(unsigned char** out, size_t* outsize, - const unsigned char* in, size_t insize, - const LodePNGCompressSettings* settings); - -#endif /*LODEPNG_COMPILE_ENCODER*/ -#endif /*LODEPNG_COMPILE_ZLIB*/ - -#ifdef LODEPNG_COMPILE_DISK -/* -Load a file from disk into buffer. The function allocates the out buffer, and -after usage you should free it. -out: output parameter, contains pointer to loaded buffer. -outsize: output parameter, size of the allocated out buffer -filename: the path to the file to load -return value: error code (0 means ok) -*/ -unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); - -/* -Save a file from buffer to disk. Warning, if it exists, this function overwrites -the file without warning! -buffer: the buffer to write -buffersize: size of the buffer to write -filename: the path to the file to save to -return value: error code (0 means ok) -*/ -unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); -#endif /*LODEPNG_COMPILE_DISK*/ - -#ifdef LODEPNG_COMPILE_CPP -/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ -namespace lodepng -{ -#ifdef LODEPNG_COMPILE_PNG - class State : public LodePNGState - { - public: - State(); - State(const State& other); - virtual ~State(); - State& operator=(const State& other); - }; - -#ifdef LODEPNG_COMPILE_DECODER - /* Same as other lodepng::decode, but using a State for more settings and information. */ - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const unsigned char* in, size_t insize); - unsigned decode(std::vector& out, unsigned& w, unsigned& h, - State& state, - const std::vector& in); -#endif /*LODEPNG_COMPILE_DECODER*/ - -#ifdef LODEPNG_COMPILE_ENCODER - /* Same as other lodepng::encode, but using a State for more settings and information. */ - unsigned encode(std::vector& out, - const unsigned char* in, unsigned w, unsigned h, - State& state); - unsigned encode(std::vector& out, - const std::vector& in, unsigned w, unsigned h, - State& state); -#endif /*LODEPNG_COMPILE_ENCODER*/ - -#ifdef LODEPNG_COMPILE_DISK - /* - Load a file from disk into an std::vector. - return value: error code (0 means ok) - */ - unsigned load_file(std::vector& buffer, const std::string& filename); - - /* - Save the binary data in an std::vector to a file on disk. The file is overwritten - without warning. - */ - unsigned save_file(const std::vector& buffer, const std::string& filename); -#endif /* LODEPNG_COMPILE_DISK */ -#endif /* LODEPNG_COMPILE_PNG */ - -#ifdef LODEPNG_COMPILE_ZLIB -#ifdef LODEPNG_COMPILE_DECODER - /* Zlib-decompress an unsigned char buffer */ - unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); - - /* Zlib-decompress an std::vector */ - unsigned decompress(std::vector& out, const std::vector& in, - const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); -#endif /* LODEPNG_COMPILE_DECODER */ - -#ifdef LODEPNG_COMPILE_ENCODER - /* Zlib-compress an unsigned char buffer */ - unsigned compress(std::vector& out, const unsigned char* in, size_t insize, - const LodePNGCompressSettings& settings = lodepng_default_compress_settings); - - /* Zlib-compress an std::vector */ - unsigned compress(std::vector& out, const std::vector& in, - const LodePNGCompressSettings& settings = lodepng_default_compress_settings); -#endif /* LODEPNG_COMPILE_ENCODER */ -#endif /* LODEPNG_COMPILE_ZLIB */ -} /* namespace lodepng */ -#endif /*LODEPNG_COMPILE_CPP*/ - -/* -TODO: -[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often -[.] check compatibility with various compilers - done but needs to be redone for every newer version -[X] converting color to 16-bit per channel types -[ ] read all public PNG chunk types (but never let the color profile and gamma ones touch RGB values) -[ ] make sure encoder generates no chunks with size > (2^31)-1 -[ ] partial decoding (stream processing) -[X] let the "isFullyOpaque" function check color keys and transparent palettes too -[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" -[ ] don't stop decoding on errors like 69, 57, 58 (make warnings) -[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... -[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes -[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... -[ ] allow user to give data (void*) to custom allocator -*/ - -#endif /*LODEPNG_H inclusion guard*/ - -/* -LodePNG Documentation ---------------------- - -0. table of contents --------------------- - - 1. about - 1.1. supported features - 1.2. features not supported - 2. C and C++ version - 3. security - 4. decoding - 5. encoding - 6. color conversions - 6.1. PNG color types - 6.2. color conversions - 6.3. padding bits - 6.4. A note about 16-bits per channel and endianness - 7. error values - 8. chunks and PNG editing - 9. compiler support - 10. examples - 10.1. decoder C++ example - 10.2. decoder C example - 11. state settings reference - 12. changes - 13. contact information - - -1. about --------- - -PNG is a file format to store raster images losslessly with good compression, -supporting different color types and alpha channel. - -LodePNG is a PNG codec according to the Portable Network Graphics (PNG) -Specification (Second Edition) - W3C Recommendation 10 November 2003. - -The specifications used are: - -*) Portable Network Graphics (PNG) Specification (Second Edition): - http://www.w3.org/TR/2003/REC-PNG-20031110 -*) RFC 1950 ZLIB Compressed Data Format version 3.3: - http://www.gzip.org/zlib/rfc-zlib.html -*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: - http://www.gzip.org/zlib/rfc-deflate.html - -The most recent version of LodePNG can currently be found at -http://lodev.org/lodepng/ - -LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds -extra functionality. - -LodePNG exists out of two files: --lodepng.h: the header file for both C and C++ --lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage - -If you want to start using LodePNG right away without reading this doc, get the -examples from the LodePNG website to see how to use it in code, or check the -smaller examples in chapter 13 here. - -LodePNG is simple but only supports the basic requirements. To achieve -simplicity, the following design choices were made: There are no dependencies -on any external library. There are functions to decode and encode a PNG with -a single function call, and extended versions of these functions taking a -LodePNGState struct allowing to specify or get more information. By default -the colors of the raw image are always RGB or RGBA, no matter what color type -the PNG file uses. To read and write files, there are simple functions to -convert the files to/from buffers in memory. - -This all makes LodePNG suitable for loading textures in games, demos and small -programs, ... It's less suitable for full fledged image editors, loading PNGs -over network (it requires all the image data to be available before decoding can -begin), life-critical systems, ... - -1.1. supported features ------------------------ - -The following features are supported by the decoder: - -*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, - or the same color type as the PNG -*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image -*) Adam7 interlace and deinterlace for any color type -*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk -*) support for alpha channels, including RGBA color model, translucent palettes and color keying -*) zlib decompression (inflate) -*) zlib compression (deflate) -*) CRC32 and ADLER32 checksums -*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. -*) the following chunks are supported (generated/interpreted) by both encoder and decoder: - IHDR: header information - PLTE: color palette - IDAT: pixel data - IEND: the final chunk - tRNS: transparency for palettized images - tEXt: textual information - zTXt: compressed textual information - iTXt: international textual information - bKGD: suggested background color - pHYs: physical dimensions - tIME: modification time - -1.2. features not supported ---------------------------- - -The following features are _not_ supported: - -*) some features needed to make a conformant PNG-Editor might be still missing. -*) partial loading/stream processing. All data must be available and is processed in one call. -*) The following public chunks are not supported but treated as unknown chunks by LodePNG - cHRM, gAMA, iCCP, sRGB, sBIT, hIST, sPLT - Some of these are not supported on purpose: LodePNG wants to provide the RGB values - stored in the pixels, not values modified by system dependent gamma or color models. - - -2. C and C++ version --------------------- - -The C version uses buffers allocated with alloc that you need to free() -yourself. You need to use init and cleanup functions for each struct whenever -using a struct from the C version to avoid exploits and memory leaks. - -The C++ version has extra functions with std::vectors in the interface and the -lodepng::State class which is a LodePNGState with constructor and destructor. - -These files work without modification for both C and C++ compilers because all -the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers -ignore it, and the C code is made to compile both with strict ISO C90 and C++. - -To use the C++ version, you need to rename the source file to lodepng.cpp -(instead of lodepng.c), and compile it with a C++ compiler. - -To use the C version, you need to rename the source file to lodepng.c (instead -of lodepng.cpp), and compile it with a C compiler. - - -3. Security ------------ - -Even if carefully designed, it's always possible that LodePNG contains possible -exploits. If you discover one, please let me know, and it will be fixed. - -When using LodePNG, care has to be taken with the C version of LodePNG, as well -as the C-style structs when working with C++. The following conventions are used -for all C-style structs: - --if a struct has a corresponding init function, always call the init function when making a new one --if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks --if a struct has a corresponding copy function, use the copy function instead of "=". - The destination must also be inited already. - - -4. Decoding ------------ - -Decoding converts a PNG compressed image to a raw pixel buffer. - -Most documentation on using the decoder is at its declarations in the header -above. For C, simple decoding can be done with functions such as -lodepng_decode32, and more advanced decoding can be done with the struct -LodePNGState and lodepng_decode. For C++, all decoding can be done with the -various lodepng::decode functions, and lodepng::State can be used for advanced -features. - -When using the LodePNGState, it uses the following fields for decoding: -*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here -*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get -*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use - -LodePNGInfo info_png --------------------- - -After decoding, this contains extra information of the PNG image, except the actual -pixels, width and height because these are already gotten directly from the decoder -functions. - -It contains for example the original color type of the PNG image, text comments, -suggested background color, etc... More details about the LodePNGInfo struct are -at its declaration documentation. - -LodePNGColorMode info_raw -------------------------- - -When decoding, here you can specify which color type you want -the resulting raw image to be. If this is different from the colortype of the -PNG, then the decoder will automatically convert the result. This conversion -always works, except if you want it to convert a color PNG to greyscale or to -a palette with missing colors. - -By default, 32-bit color is used for the result. - -LodePNGDecoderSettings decoder ------------------------------- - -The settings can be used to ignore the errors created by invalid CRC and Adler32 -chunks, and to disable the decoding of tEXt chunks. - -There's also a setting color_convert, true by default. If false, no conversion -is done, the resulting data will be as it was in the PNG (after decompression) -and you'll have to puzzle the colors of the pixels together yourself using the -color type information in the LodePNGInfo. - - -5. Encoding ------------ - -Encoding converts a raw pixel buffer to a PNG compressed image. - -Most documentation on using the encoder is at its declarations in the header -above. For C, simple encoding can be done with functions such as -lodepng_encode32, and more advanced decoding can be done with the struct -LodePNGState and lodepng_encode. For C++, all encoding can be done with the -various lodepng::encode functions, and lodepng::State can be used for advanced -features. - -Like the decoder, the encoder can also give errors. However it gives less errors -since the encoder input is trusted, the decoder input (a PNG image that could -be forged by anyone) is not trusted. - -When using the LodePNGState, it uses the following fields for encoding: -*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. -*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has -*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use - -LodePNGInfo info_png --------------------- - -When encoding, you use this the opposite way as when decoding: for encoding, -you fill in the values you want the PNG to have before encoding. By default it's -not needed to specify a color type for the PNG since it's automatically chosen, -but it's possible to choose it yourself given the right settings. - -The encoder will not always exactly match the LodePNGInfo struct you give, -it tries as close as possible. Some things are ignored by the encoder. The -encoder uses, for example, the following settings from it when applicable: -colortype and bitdepth, text chunks, time chunk, the color key, the palette, the -background color, the interlace method, unknown chunks, ... - -When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. -If the palette contains any colors for which the alpha channel is not 255 (so -there are translucent colors in the palette), it'll add a tRNS chunk. - -LodePNGColorMode info_raw -------------------------- - -You specify the color type of the raw image that you give to the input here, -including a possible transparent color key and palette you happen to be using in -your raw image data. - -By default, 32-bit color is assumed, meaning your input has to be in RGBA -format with 4 bytes (unsigned chars) per pixel. - -LodePNGEncoderSettings encoder ------------------------------- - -The following settings are supported (some are in sub-structs): -*) auto_convert: when this option is enabled, the encoder will -automatically choose the smallest possible color mode (including color key) that -can encode the colors of all pixels without information loss. -*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, - 2 = dynamic huffman tree (best compression). Should be 2 for proper - compression. -*) use_lz77: whether or not to use LZ77 for compressed block types. Should be - true for proper compression. -*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value - 2048 by default, but can be set to 32768 for better, but slow, compression. -*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE - chunk if force_palette is true. This can used as suggested palette to convert - to by viewers that don't support more than 256 colors (if those still exist) -*) add_id: add text chunk "Encoder: LodePNG " to the image. -*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. - zTXt chunks use zlib compression on the text. This gives a smaller result on - large texts but a larger result on small texts (such as a single program name). - It's all tEXt or all zTXt though, there's no separate setting per text yet. - - -6. color conversions --------------------- - -An important thing to note about LodePNG, is that the color type of the PNG, and -the color type of the raw image, are completely independent. By default, when -you decode a PNG, you get the result as a raw image in the color type you want, -no matter whether the PNG was encoded with a palette, greyscale or RGBA color. -And if you encode an image, by default LodePNG will automatically choose the PNG -color type that gives good compression based on the values of colors and amount -of colors in the image. It can be configured to let you control it instead as -well, though. - -To be able to do this, LodePNG does conversions from one color mode to another. -It can convert from almost any color type to any other color type, except the -following conversions: RGB to greyscale is not supported, and converting to a -palette when the palette doesn't have a required color is not supported. This is -not supported on purpose: this is information loss which requires a color -reduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to grey -is easy, but there are multiple ways if you want to give some channels more -weight). - -By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB -color, no matter what color type the PNG has. And by default when encoding, -LodePNG automatically picks the best color model for the output PNG, and expects -the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control -the color format of the images yourself, you can skip this chapter. - -6.1. PNG color types --------------------- - -A PNG image can have many color types, ranging from 1-bit color to 64-bit color, -as well as palettized color modes. After the zlib decompression and unfiltering -in the PNG image is done, the raw pixel data will have that color type and thus -a certain amount of bits per pixel. If you want the output raw image after -decoding to have another color type, a conversion is done by LodePNG. - -The PNG specification gives the following color types: - -0: greyscale, bit depths 1, 2, 4, 8, 16 -2: RGB, bit depths 8 and 16 -3: palette, bit depths 1, 2, 4 and 8 -4: greyscale with alpha, bit depths 8 and 16 -6: RGBA, bit depths 8 and 16 - -Bit depth is the amount of bits per pixel per color channel. So the total amount -of bits per pixel is: amount of channels * bitdepth. - -6.2. color conversions ----------------------- - -As explained in the sections about the encoder and decoder, you can specify -color types and bit depths in info_png and info_raw to change the default -behaviour. - -If, when decoding, you want the raw image to be something else than the default, -you need to set the color type and bit depth you want in the LodePNGColorMode, -or the parameters colortype and bitdepth of the simple decoding function. - -If, when encoding, you use another color type than the default in the raw input -image, you need to specify its color type and bit depth in the LodePNGColorMode -of the raw image, or use the parameters colortype and bitdepth of the simple -encoding function. - -If, when encoding, you don't want LodePNG to choose the output PNG color type -but control it yourself, you need to set auto_convert in the encoder settings -to false, and specify the color type you want in the LodePNGInfo of the -encoder (including palette: it can generate a palette if auto_convert is true, -otherwise not). - -If the input and output color type differ (whether user chosen or auto chosen), -LodePNG will do a color conversion, which follows the rules below, and may -sometimes result in an error. - -To avoid some confusion: --the decoder converts from PNG to raw image --the encoder converts from raw image to PNG --the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image --the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG --when encoding, the color type in LodePNGInfo is ignored if auto_convert - is enabled, it is automatically generated instead --when decoding, the color type in LodePNGInfo is set by the decoder to that of the original - PNG image, but it can be ignored since the raw image has the color type you requested instead --if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion - between the color types is done if the color types are supported. If it is not - supported, an error is returned. If the types are the same, no conversion is done. --even though some conversions aren't supported, LodePNG supports loading PNGs from any - colortype and saving PNGs to any colortype, sometimes it just requires preparing - the raw image correctly before encoding. --both encoder and decoder use the same color converter. - -Non supported color conversions: --color to greyscale: no error is thrown, but the result will look ugly because -only the red channel is taken --anything to palette when that palette does not have that color in it: in this -case an error is thrown - -Supported color conversions: --anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA --any grey or grey+alpha, to grey or grey+alpha --anything to a palette, as long as the palette has the requested colors in it --removing alpha channel --higher to smaller bitdepth, and vice versa - -If you want no color conversion to be done (e.g. for speed or control): --In the encoder, you can make it save a PNG with any color type by giving the -raw color mode and LodePNGInfo the same color mode, and setting auto_convert to -false. --In the decoder, you can make it store the pixel data in the same color type -as the PNG has, by setting the color_convert setting to false. Settings in -info_raw are then ignored. - -The function lodepng_convert does the color conversion. It is available in the -interface but normally isn't needed since the encoder and decoder already call -it. - -6.3. padding bits ------------------ - -In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines -have a bit amount that isn't a multiple of 8, then padding bits are used so that each -scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. -The raw input image you give to the encoder, and the raw output image you get from the decoder -will NOT have these padding bits, e.g. in the case of a 1-bit image with a width -of 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte, -not the first bit of a new byte. - -6.4. A note about 16-bits per channel and endianness ----------------------------------------------------- - -LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like -for any other color format. The 16-bit values are stored in big endian (most -significant byte first) in these arrays. This is the opposite order of the -little endian used by x86 CPU's. - -LodePNG always uses big endian because the PNG file format does so internally. -Conversions to other formats than PNG uses internally are not supported by -LodePNG on purpose, there are myriads of formats, including endianness of 16-bit -colors, the order in which you store R, G, B and A, and so on. Supporting and -converting to/from all that is outside the scope of LodePNG. - -This may mean that, depending on your use case, you may want to convert the big -endian output of LodePNG to little endian with a for loop. This is certainly not -always needed, many applications and libraries support big endian 16-bit colors -anyway, but it means you cannot simply cast the unsigned char* buffer to an -unsigned short* buffer on x86 CPUs. - - -7. error values ---------------- - -All functions in LodePNG that return an error code, return 0 if everything went -OK, or a non-zero code if there was an error. - -The meaning of the LodePNG error values can be retrieved with the function -lodepng_error_text: given the numerical error code, it returns a description -of the error in English as a string. - -Check the implementation of lodepng_error_text to see the meaning of each code. - - -8. chunks and PNG editing -------------------------- - -If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG -editor that should follow the rules about handling of unknown chunks, or if your -program is able to read other types of chunks than the ones handled by LodePNG, -then that's possible with the chunk functions of LodePNG. - -A PNG chunk has the following layout: - -4 bytes length -4 bytes type name -length bytes data -4 bytes CRC - -8.1. iterating through chunks ------------------------------ - -If you have a buffer containing the PNG image data, then the first chunk (the -IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the -signature of the PNG and are not part of a chunk. But if you start at byte 8 -then you have a chunk, and can check the following things of it. - -NOTE: none of these functions check for memory buffer boundaries. To avoid -exploits, always make sure the buffer contains all the data of the chunks. -When using lodepng_chunk_next, make sure the returned value is within the -allocated memory. - -unsigned lodepng_chunk_length(const unsigned char* chunk): - -Get the length of the chunk's data. The total chunk length is this length + 12. - -void lodepng_chunk_type(char type[5], const unsigned char* chunk): -unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): - -Get the type of the chunk or compare if it's a certain type - -unsigned char lodepng_chunk_critical(const unsigned char* chunk): -unsigned char lodepng_chunk_private(const unsigned char* chunk): -unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): - -Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). -Check if the chunk is private (public chunks are part of the standard, private ones not). -Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical -chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your -program doesn't handle that type of unknown chunk. - -unsigned char* lodepng_chunk_data(unsigned char* chunk): -const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): - -Get a pointer to the start of the data of the chunk. - -unsigned lodepng_chunk_check_crc(const unsigned char* chunk): -void lodepng_chunk_generate_crc(unsigned char* chunk): - -Check if the crc is correct or generate a correct one. - -unsigned char* lodepng_chunk_next(unsigned char* chunk): -const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): - -Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these -functions do no boundary checking of the allocated data whatsoever, so make sure there is enough -data available in the buffer to be able to go to the next chunk. - -unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk): -unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, - const char* type, const unsigned char* data): - -These functions are used to create new chunks that are appended to the data in *out that has -length *outlength. The append function appends an existing chunk to the new data. The create -function creates a new chunk with the given parameters and appends it. Type is the 4-letter -name of the chunk. - -8.2. chunks in info_png ------------------------ - -The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 -buffers (each with size) to contain 3 types of unknown chunks: -the ones that come before the PLTE chunk, the ones that come between the PLTE -and the IDAT chunks, and the ones that come after the IDAT chunks. -It's necessary to make the distionction between these 3 cases because the PNG -standard forces to keep the ordering of unknown chunks compared to the critical -chunks, but does not force any other ordering rules. - -info_png.unknown_chunks_data[0] is the chunks before PLTE -info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT -info_png.unknown_chunks_data[2] is the chunks after IDAT - -The chunks in these 3 buffers can be iterated through and read by using the same -way described in the previous subchapter. - -When using the decoder to decode a PNG, you can make it store all unknown chunks -if you set the option settings.remember_unknown_chunks to 1. By default, this -option is off (0). - -The encoder will always encode unknown chunks that are stored in the info_png. -If you need it to add a particular chunk that isn't known by LodePNG, you can -use lodepng_chunk_append or lodepng_chunk_create to the chunk data in -info_png.unknown_chunks_data[x]. - -Chunks that are known by LodePNG should not be added in that way. E.g. to make -LodePNG add a bKGD chunk, set background_defined to true and add the correct -parameters there instead. - - -9. compiler support -------------------- - -No libraries other than the current standard C library are needed to compile -LodePNG. For the C++ version, only the standard C++ library is needed on top. -Add the files lodepng.c(pp) and lodepng.h to your project, include -lodepng.h where needed, and your program can read/write PNG files. - -It is compatible with C90 and up, and C++03 and up. - -If performance is important, use optimization when compiling! For both the -encoder and decoder, this makes a large difference. - -Make sure that LodePNG is compiled with the same compiler of the same version -and with the same settings as the rest of the program, or the interfaces with -std::vectors and std::strings in C++ can be incompatible. - -CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. - -*) gcc and g++ - -LodePNG is developed in gcc so this compiler is natively supported. It gives no -warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ -version 4.7.1 on Linux, 32-bit and 64-bit. - -*) Clang - -Fully supported and warning-free. - -*) Mingw - -The Mingw compiler (a port of gcc for Windows) should be fully supported by -LodePNG. - -*) Visual Studio and Visual C++ Express Edition - -LodePNG should be warning-free with warning level W4. Two warnings were disabled -with pragmas though: warning 4244 about implicit conversions, and warning 4996 -where it wants to use a non-standard function fopen_s instead of the standard C -fopen. - -Visual Studio may want "stdafx.h" files to be included in each source file and -give an error "unexpected end of file while looking for precompiled header". -This is not standard C++ and will not be added to the stock LodePNG. You can -disable it for lodepng.cpp only by right clicking it, Properties, C/C++, -Precompiled Headers, and set it to Not Using Precompiled Headers there. - -NOTE: Modern versions of VS should be fully supported, but old versions, e.g. -VS6, are not guaranteed to work. - -*) Compilers on Macintosh - -LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for -C and C++. - -*) Other Compilers - -If you encounter problems on any compilers, feel free to let me know and I may -try to fix it if the compiler is modern and standards complient. - - -10. examples ------------- - -This decoder example shows the most basic usage of LodePNG. More complex -examples can be found on the LodePNG website. - -10.1. decoder C++ example -------------------------- - -#include "lodepng.h" -#include - -int main(int argc, char *argv[]) -{ - const char* filename = argc > 1 ? argv[1] : "test.png"; - - //load and decode - std::vector image; - unsigned width, height; - unsigned error = lodepng::decode(image, width, height, filename); - - //if there's an error, display it - if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; - - //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... -} - -10.2. decoder C example ------------------------ - -#include "lodepng.h" - -int main(int argc, char *argv[]) -{ - unsigned error; - unsigned char* image; - size_t width, height; - const char* filename = argc > 1 ? argv[1] : "test.png"; - - error = lodepng_decode32_file(&image, &width, &height, filename); - - if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); - - / * use image here * / - - free(image); - return 0; -} - -11. state settings reference ----------------------------- - -A quick reference of some settings to set on the LodePNGState - -For decoding: - -state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums -state.decoder.zlibsettings.custom_...: use custom inflate function -state.decoder.ignore_crc: ignore CRC checksums -state.decoder.color_convert: convert internal PNG color to chosen one -state.decoder.read_text_chunks: whether to read in text metadata chunks -state.decoder.remember_unknown_chunks: whether to read in unknown chunks -state.info_raw.colortype: desired color type for decoded image -state.info_raw.bitdepth: desired bit depth for decoded image -state.info_raw....: more color settings, see struct LodePNGColorMode -state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo - -For encoding: - -state.encoder.zlibsettings.btype: disable compression by setting it to 0 -state.encoder.zlibsettings.use_lz77: use LZ77 in compression -state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize -state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match -state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching -state.encoder.zlibsettings.lazymatching: try one more LZ77 matching -state.encoder.zlibsettings.custom_...: use custom deflate function -state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png -state.encoder.filter_palette_zero: PNG filter strategy for palette -state.encoder.filter_strategy: PNG filter strategy to encode with -state.encoder.force_palette: add palette even if not encoding to one -state.encoder.add_id: add LodePNG identifier and version as a text chunk -state.encoder.text_compression: use compressed text chunks for metadata -state.info_raw.colortype: color type of raw input image you provide -state.info_raw.bitdepth: bit depth of raw input image you provide -state.info_raw: more color settings, see struct LodePNGColorMode -state.info_png.color.colortype: desired color type if auto_convert is false -state.info_png.color.bitdepth: desired bit depth if auto_convert is false -state.info_png.color....: more color settings, see struct LodePNGColorMode -state.info_png....: more PNG related settings, see struct LodePNGInfo - - -12. changes ------------ - -The version number of LodePNG is the date of the change given in the format -yyyymmdd. - -Some changes aren't backwards compatible. Those are indicated with a (!) -symbol. - -*) 27 nov 2016: grey+alpha auto color model detection bugfix -*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). -*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within - the limits of pure C90). -*) 08 dec 2015: Made load_file function return error if file can't be opened. -*) 24 okt 2015: Bugfix with decoding to palette output. -*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. -*) 23 aug 2014: Reduced needless memory usage of decoder. -*) 28 jun 2014: Removed fix_png setting, always support palette OOB for - simplicity. Made ColorProfile public. -*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. -*) 22 dec 2013: Power of two windowsize required for optimization. -*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. -*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). -*) 11 mar 2013 (!): Bugfix with custom free. Changed from "my" to "lodepng_" - prefix for the custom allocators and made it possible with a new #define to - use custom ones in your project without needing to change lodepng's code. -*) 28 jan 2013: Bugfix with color key. -*) 27 okt 2012: Tweaks in text chunk keyword length error handling. -*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode. - (no palette). Better deflate tree encoding. New compression tweak settings. - Faster color conversions while decoding. Some internal cleanups. -*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. -*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions - and made it work with function pointers instead. -*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc - and free functions and toggle #defines from compiler flags. Small fixes. -*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible. -*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed - redundant C++ codec classes. Reduced amount of structs. Everything changed, - but it is cleaner now imho and functionality remains the same. Also fixed - several bugs and shrunk the implementation code. Made new samples. -*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best - PNG color model and bit depth, based on the amount and type of colors of the - raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. -*) 9 okt 2011: simpler hash chain implementation for the encoder. -*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. -*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. - A bug with the PNG filtertype heuristic was fixed, so that it chooses much - better ones (it's quite significant). A setting to do an experimental, slow, - brute force search for PNG filter types is added. -*) 17 aug 2011 (!): changed some C zlib related function names. -*) 16 aug 2011: made the code less wide (max 120 characters per line). -*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. -*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. -*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman - to optimize long sequences of zeros. -*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and - LodePNG_InfoColor_canHaveAlpha functions for convenience. -*) 7 nov 2010: added LodePNG_error_text function to get error code description. -*) 30 okt 2010: made decoding slightly faster -*) 26 okt 2010: (!) changed some C function and struct names (more consistent). - Reorganized the documentation and the declaration order in the header. -*) 08 aug 2010: only changed some comments and external samples. -*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. -*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. -*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could - read by ignoring the problem but windows apps couldn't. -*) 06 jun 2008: added more error checks for out of memory cases. -*) 26 apr 2008: added a few more checks here and there to ensure more safety. -*) 06 mar 2008: crash with encoding of strings fixed -*) 02 feb 2008: support for international text chunks added (iTXt) -*) 23 jan 2008: small cleanups, and #defines to divide code in sections -*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. -*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. -*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added - Also various fixes, such as in the deflate and the padding bits code. -*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved - filtering code of encoder. -*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A - C++ wrapper around this provides an interface almost identical to before. - Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code - are together in these files but it works both for C and C++ compilers. -*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks -*) 30 aug 2007: bug fixed which makes this Borland C++ compatible -*) 09 aug 2007: some VS2005 warnings removed again -*) 21 jul 2007: deflate code placed in new namespace separate from zlib code -*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images -*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing - invalid std::vector element [0] fixed, and level 3 and 4 warnings removed -*) 02 jun 2007: made the encoder add a tag with version by default -*) 27 may 2007: zlib and png code separated (but still in the same file), - simple encoder/decoder functions added for more simple usage cases -*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), - moved some examples from here to lodepng_examples.cpp -*) 12 may 2007: palette decoding bug fixed -*) 24 apr 2007: changed the license from BSD to the zlib license -*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. -*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding - palettized PNG images. Plus little interface change with palette and texts. -*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. - Fixed a bug where the end code of a block had length 0 in the Huffman tree. -*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented - and supported by the encoder, resulting in smaller PNGs at the output. -*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. -*) 24 jan 2007: gave encoder an error interface. Added color conversion from any - greyscale type to 8-bit greyscale with or without alpha. -*) 21 jan 2007: (!) Totally changed the interface. It allows more color types - to convert to and is more uniform. See the manual for how it works now. -*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: - encode/decode custom tEXt chunks, separate classes for zlib & deflate, and - at last made the decoder give errors for incorrect Adler32 or Crc. -*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. -*) 29 dec 2006: Added support for encoding images without alpha channel, and - cleaned out code as well as making certain parts faster. -*) 28 dec 2006: Added "Settings" to the encoder. -*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. - Removed some code duplication in the decoder. Fixed little bug in an example. -*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. - Fixed a bug of the decoder with 16-bit per color. -*) 15 okt 2006: Changed documentation structure -*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the - given image buffer, however for now it's not compressed. -*) 08 sep 2006: (!) Changed to interface with a Decoder class -*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different - way. Renamed decodePNG to decodePNGGeneric. -*) 29 jul 2006: (!) Changed the interface: image info is now returned as a - struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. -*) 28 jul 2006: Cleaned the code and added new error checks. - Corrected terminology "deflate" into "inflate". -*) 23 jun 2006: Added SDL example in the documentation in the header, this - example allows easy debugging by displaying the PNG and its transparency. -*) 22 jun 2006: (!) Changed way to obtain error value. Added - loadFile function for convenience. Made decodePNG32 faster. -*) 21 jun 2006: (!) Changed type of info vector to unsigned. - Changed position of palette in info vector. Fixed an important bug that - happened on PNGs with an uncompressed block. -*) 16 jun 2006: Internally changed unsigned into unsigned where - needed, and performed some optimizations. -*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them - in LodePNG namespace. Changed the order of the parameters. Rewrote the - documentation in the header. Renamed files to lodepng.cpp and lodepng.h -*) 22 apr 2006: Optimized and improved some code -*) 07 sep 2005: (!) Changed to std::vector interface -*) 12 aug 2005: Initial release (C++, decoder only) - - -13. contact information ------------------------ - -Feel free to contact me with suggestions, problems, comments, ... concerning -LodePNG. If you encounter a PNG image that doesn't work properly with this -decoder, feel free to send it and I'll use it to find and fix the problem. - -My email address is (puzzle the account and domain together with an @ symbol): -Domain: gmail dot com. -Account: lode dot vandevenne. - - -Copyright (c) 2005-2016 Lode Vandevenne -*/