/*! * \file galileo_e1b_reed_solomon_test.cc * \brief Tests for Reed Solomon E1B encoder and decoder * \author Carles Fernandez-Prades, 2021. cfernandez(at)cttc.es * * * ----------------------------------------------------------------------------- * * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * * Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- */ #include "gnss_sdr_make_unique.h" #include "reed_solomon.h" #include TEST(ReedSolomonE1BTest, EncodeWithPoly) { const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; const std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; auto rs = std::make_unique("E1B"); std::vector encoded_output = rs->encode_with_generator_poly(information_vector); EXPECT_TRUE(encoded_output == code_vector); } TEST(ReedSolomonE1BTest, EncodeWithCustomPoly) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; const std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; // Instantiate a ReedSolomon object with Galileo E1 (INAV) parameters const int nroots = 60; const int minpoly = 29; const int pad = 0; const int prim = 1; const int fcr = 195; const int shortening = 137; const std::vector genpoly_coeff = {1, 208, 42, 48, 76, 19, 41, 108, 167, 235, 166, 244, 186, 18, 124, 251, 79, 193, 14, 154, 6, 118, 19, 3, 122, 9, 187, 42, 131, 46, 66, 65, 62, 94, 101, 45, 214, 141, 131, 230, 102, 20, 63, 202, 36, 23, 188, 88, 169, 62, 73, 88, 152, 197, 231, 58, 101, 154, 190, 91, 193}; auto rs = std::make_unique(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff); std::vector encoded_output = rs->encode_with_generator_poly(information_vector); EXPECT_TRUE(encoded_output == code_vector); } TEST(ReedSolomonE1BTest, EncodeWithMatrix) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; const std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; auto rs = std::make_unique("E1B"); std::vector encoded_output = rs->encode_with_generator_matrix(information_vector); EXPECT_TRUE(code_vector == encoded_output); } TEST(ReedSolomonE1BTest, EncodeWithCustomMatrix) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; const std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; const int nroots = 60; const int minpoly = 29; const int prim = 1; const int fcr = 195; const int pad = 0; const int shortening = 137; const std::vector genpoly_coeff; const std::vector> genmatrix = { {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, {193, 146, 156, 183, 62, 35, 90, 25, 89, 208, 43, 148, 117, 199, 92, 112, 4, 70, 74, 183, 37, 100, 118, 44, 238, 107, 186, 200, 179, 63, 140, 194, 176, 131, 38, 110, 33, 178, 43, 173, 98, 96, 105, 115, 90, 76, 133, 194, 133, 182, 99, 20, 183, 90, 84, 131, 26, 139}, {91, 221, 65, 59, 102, 79, 66, 118, 29, 43, 164, 253, 13, 228, 108, 106, 252, 230, 45, 237, 12, 149, 152, 235, 143, 178, 102, 199, 227, 65, 230, 178, 140, 133, 93, 213, 89, 41, 198, 197, 215, 94, 122, 58, 18, 251, 179, 187, 61, 1, 239, 229, 179, 214, 244, 97, 202, 42}, {190, 173, 125, 234, 225, 164, 122, 176, 130, 152, 32, 205, 41, 44, 78, 230, 128, 101, 92, 134, 176, 227, 128, 184, 180, 130, 142, 165, 134, 141, 110, 153, 50, 65, 25, 14, 98, 172, 34, 94, 181, 210, 38, 49, 15, 55, 169, 204, 233, 34, 197, 138, 78, 134, 181, 57, 82, 206}, {154, 48, 226, 109, 5, 179, 159, 79, 237, 32, 199, 98, 33, 127, 219, 8, 110, 36, 68, 76, 24, 100, 105, 49, 245, 131, 53, 59, 61, 75, 216, 146, 103, 132, 185, 132, 24, 216, 243, 97, 70, 233, 161, 6, 10, 226, 77, 85, 182, 219, 24, 87, 154, 117, 124, 3, 106, 233}, {101, 12, 238, 213, 120, 140, 44, 51, 196, 68, 201, 121, 36, 108, 200, 161, 56, 97, 123, 115, 237, 146, 54, 164, 141, 59, 232, 60, 60, 36, 85, 169, 129, 61, 49, 75, 21, 19, 49, 124, 195, 252, 63, 207, 153, 125, 144, 60, 39, 141, 117, 232, 96, 5, 162, 38, 187, 80}, {58, 136, 130, 2, 173, 144, 135, 249, 194, 161, 38, 205, 85, 247, 142, 247, 228, 245, 99, 151, 114, 158, 68, 235, 185, 203, 78, 14, 149, 18, 163, 149, 250, 51, 198, 100, 15, 234, 113, 242, 230, 245, 22, 250, 196, 114, 38, 80, 103, 157, 65, 57, 4, 107, 109, 16, 9, 131}, {231, 109, 52, 176, 87, 22, 48, 253, 54, 106, 47, 175, 119, 108, 137, 133, 99, 143, 63, 81, 242, 135, 75, 49, 22, 130, 125, 185, 168, 229, 196, 43, 92, 226, 57, 76, 149, 140, 100, 86, 217, 135, 132, 114, 90, 208, 180, 174, 150, 112, 147, 191, 11, 164, 32, 117, 5, 36}, {197, 18, 114, 255, 50, 100, 185, 124, 218, 88, 190, 215, 41, 191, 206, 138, 120, 5, 243, 244, 111, 223, 137, 234, 221, 169, 43, 39, 143, 82, 41, 137, 149, 2, 84, 3, 143, 219, 88, 107, 118, 9, 200, 15, 221, 43, 131, 249, 253, 37, 40, 189, 116, 164, 225, 126, 177, 188}, {152, 246, 146, 92, 78, 104, 171, 40, 30, 39, 246, 202, 204, 246, 55, 63, 240, 204, 63, 221, 233, 17, 105, 240, 166, 128, 153, 215, 115, 174, 39, 28, 112, 195, 178, 227, 100, 75, 117, 74, 82, 114, 105, 148, 192, 160, 58, 182, 232, 67, 140, 167, 147, 187, 216, 183, 66, 19}, {88, 233, 3, 20, 252, 51, 135, 113, 130, 146, 84, 13, 81, 30, 147, 99, 56, 10, 63, 185, 42, 166, 207, 88, 220, 165, 199, 7, 86, 27, 71, 58, 216, 213, 113, 126, 19, 45, 56, 108, 143, 26, 252, 120, 123, 185, 143, 39, 153, 166, 78, 151, 33, 124, 208, 125, 40, 233}, {73, 120, 195, 119, 81, 197, 85, 70, 175, 109, 204, 25, 136, 117, 21, 195, 222, 74, 162, 75, 237, 9, 155, 148, 242, 157, 99, 129, 206, 123, 255, 182, 75, 94, 57, 229, 151, 178, 115, 53, 34, 17, 139, 20, 30, 190, 82, 126, 204, 133, 128, 61, 227, 71, 16, 86, 4, 201}, {62, 195, 117, 83, 179, 169, 59, 213, 201, 116, 240, 164, 198, 84, 105, 89, 127, 51, 126, 50, 81, 215, 167, 203, 139, 96, 251, 23, 173, 37, 188, 176, 235, 36, 53, 56, 67, 148, 47, 18, 237, 164, 221, 182, 234, 200, 51, 29, 243, 115, 114, 246, 173, 29, 62, 127, 167, 14}, {169, 67, 240, 110, 142, 45, 20, 35, 20, 206, 92, 117, 106, 151, 17, 35, 2, 94, 255, 101, 84, 49, 101, 168, 17, 122, 73, 59, 87, 175, 103, 105, 140, 56, 62, 64, 5, 220, 188, 80, 138, 214, 246, 235, 11, 222, 227, 230, 54, 55, 52, 88, 237, 16, 238, 237, 27, 194}, {88, 216, 182, 118, 206, 243, 194, 206, 137, 152, 189, 167, 238, 184, 242, 69, 36, 248, 173, 121, 146, 27, 239, 84, 132, 18, 61, 215, 186, 63, 70, 122, 173, 41, 138, 242, 176, 76, 175, 165, 149, 194, 88, 231, 4, 114, 241, 254, 201, 120, 58, 47, 222, 2, 123, 75, 114, 176}, {188, 19, 183, 35, 242, 4, 50, 148, 5, 83, 98, 226, 132, 70, 109, 207, 93, 173, 89, 56, 167, 215, 50, 7, 10, 227, 169, 183, 90, 56, 48, 240, 253, 128, 253, 243, 52, 59, 182, 102, 244, 200, 169, 111, 38, 177, 75, 71, 199, 90, 47, 66, 186, 31, 231, 86, 23, 111}, {23, 55, 128, 7, 36, 174, 140, 216, 161, 135, 112, 142, 248, 244, 169, 173, 126, 229, 219, 233, 3, 40, 112, 29, 130, 246, 246, 170, 182, 54, 85, 154, 76, 227, 6, 219, 121, 94, 24, 81, 142, 202, 226, 212, 231, 55, 200, 225, 62, 28, 217, 96, 242, 50, 143, 249, 1, 118}, {36, 111, 216, 59, 50, 180, 160, 75, 113, 134, 211, 91, 182, 143, 169, 101, 207, 67, 126, 96, 42, 56, 183, 225, 15, 184, 125, 128, 115, 21, 76, 214, 228, 55, 135, 200, 122, 54, 10, 195, 57, 215, 193, 137, 218, 47, 31, 75, 201, 19, 226, 46, 219, 252, 171, 244, 153, 190}, {202, 21, 206, 182, 17, 61, 151, 229, 64, 62, 73, 178, 215, 44, 252, 93, 5, 209, 253, 16, 63, 35, 156, 48, 132, 142, 110, 111, 142, 65, 41, 174, 240, 80, 64, 126, 247, 108, 249, 9, 154, 80, 102, 29, 170, 52, 203, 253, 175, 191, 82, 31, 64, 248, 79, 31, 153, 237}, {63, 144, 241, 65, 93, 237, 185, 69, 251, 58, 85, 58, 152, 193, 129, 101, 152, 224, 102, 114, 197, 80, 147, 168, 161, 35, 37, 176, 37, 19, 150, 140, 126, 239, 31, 84, 110, 203, 7, 62, 79, 48, 27, 101, 153, 52, 2, 110, 203, 86, 143, 164, 144, 196, 194, 80, 87, 17}, {20, 217, 37, 96, 55, 13, 235, 165, 222, 135, 30, 148, 34, 171, 224, 35, 95, 56, 14, 247, 5, 181, 213, 16, 162, 2, 124, 197, 27, 211, 78, 31, 186, 240, 5, 6, 25, 69, 239, 23, 105, 5, 142, 36, 99, 80, 157, 139, 199, 218, 129, 93, 53, 150, 145, 76, 209, 173}, {102, 239, 33, 51, 4, 178, 28, 177, 128, 137, 105, 141, 208, 44, 210, 248, 152, 72, 255, 24, 26, 112, 197, 180, 35, 51, 35, 150, 104, 152, 253, 28, 134, 112, 41, 200, 80, 83, 171, 151, 10, 167, 71, 162, 53, 204, 242, 207, 41, 54, 32, 236, 75, 36, 132, 91, 34, 112}, {230, 225, 186, 12, 73, 187, 104, 52, 239, 137, 241, 251, 194, 35, 227, 12, 21, 251, 1, 210, 178, 186, 187, 212, 199, 45, 72, 126, 86, 110, 94, 159, 88, 238, 94, 182, 143, 236, 43, 42, 34, 71, 81, 29, 120, 105, 177, 144, 178, 120, 255, 94, 193, 145, 44, 236, 247, 141}, {131, 247, 106, 160, 99, 127, 254, 236, 225, 79, 24, 221, 242, 124, 91, 71, 209, 121, 237, 27, 217, 152, 35, 103, 27, 7, 61, 28, 185, 73, 182, 77, 200, 106, 117, 51, 96, 56, 125, 37, 61, 213, 103, 101, 88, 83, 102, 162, 159, 216, 31, 113, 68, 132, 78, 30, 248, 98}, {141, 134, 43, 202, 72, 109, 204, 33, 132, 193, 51, 182, 43, 212, 100, 221, 126, 205, 46, 77, 190, 130, 181, 189, 175, 208, 165, 139, 133, 24, 113, 224, 15, 96, 20, 206, 175, 176, 68, 217, 213, 95, 140, 58, 214, 164, 80, 48, 161, 118, 97, 194, 209, 247, 238, 230, 26, 34}, {214, 148, 137, 44, 243, 55, 191, 63, 77, 214, 201, 75, 217, 156, 103, 212, 104, 128, 241, 41, 83, 85, 83, 182, 214, 56, 127, 110, 57, 214, 249, 25, 236, 146, 192, 92, 101, 119, 184, 14, 83, 139, 28, 130, 232, 139, 88, 56, 204, 204, 150, 58, 197, 3, 51, 115, 171, 240}, {45, 176, 137, 213, 83, 71, 180, 128, 251, 170, 151, 33, 125, 122, 145, 152, 32, 29, 244, 173, 19, 175, 36, 161, 46, 108, 88, 154, 198, 123, 60, 147, 246, 64, 239, 179, 146, 240, 54, 156, 124, 91, 75, 164, 1, 18, 169, 50, 26, 173, 131, 149, 102, 70, 251, 159, 11, 242}, {101, 187, 110, 190, 192, 218, 216, 24, 11, 82, 67, 41, 103, 48, 205, 235, 168, 47, 66, 195, 12, 153, 253, 233, 29, 224, 7, 81, 157, 223, 101, 77, 128, 172, 245, 29, 34, 153, 25, 185, 62, 198, 141, 37, 59, 118, 96, 216, 64, 33, 3, 115, 162, 249, 145, 161, 39, 49}, {94, 206, 2, 170, 252, 165, 52, 243, 243, 102, 47, 226, 182, 51, 212, 93, 231, 98, 241, 134, 172, 160, 3, 137, 198, 160, 51, 66, 153, 220, 86, 62, 128, 24, 198, 71, 126, 233, 228, 243, 31, 158, 125, 24, 203, 239, 228, 59, 74, 135, 132, 63, 183, 76, 5, 9, 143, 167}, {62, 212, 195, 146, 110, 4, 91, 180, 124, 40, 251, 71, 61, 106, 47, 152, 225, 10, 86, 97, 156, 150, 14, 83, 150, 84, 198, 71, 110, 114, 27, 25, 99, 239, 115, 199, 225, 125, 116, 133, 43, 153, 82, 64, 230, 29, 98, 171, 182, 245, 112, 242, 175, 73, 53, 106, 248, 133}, {65, 208, 229, 79, 178, 119, 149, 48, 150, 242, 149, 110, 57, 7, 128, 153, 202, 211, 206, 218, 3, 45, 91, 82, 253, 98, 180, 185, 153, 212, 22, 233, 116, 66, 62, 79, 247, 165, 192, 32, 79, 200, 68, 87, 209, 89, 71, 144, 241, 160, 165, 119, 126, 62, 7, 20, 178, 125}, {66, 194, 199, 72, 30, 167, 104, 8, 188, 230, 72, 45, 18, 64, 35, 84, 64, 224, 143, 99, 244, 77, 194, 171, 115, 86, 200, 40, 205, 185, 128, 199, 14, 197, 255, 61, 184, 242, 31, 99, 85, 216, 129, 3, 72, 182, 211, 150, 26, 45, 164, 63, 218, 97, 181, 182, 26, 172}, {46, 73, 249, 186, 70, 166, 170, 161, 98, 165, 160, 141, 25, 242, 131, 190, 43, 45, 12, 242, 21, 247, 30, 156, 188, 150, 124, 206, 42, 21, 99, 201, 162, 50, 212, 179, 52, 108, 180, 204, 174, 41, 140, 123, 14, 106, 68, 154, 100, 177, 54, 58, 66, 215, 92, 137, 24, 216}, {131, 63, 194, 227, 213, 112, 227, 46, 116, 194, 52, 140, 132, 167, 138, 39, 99, 71, 59, 22, 249, 63, 110, 194, 83, 124, 134, 40, 9, 53, 205, 112, 158, 144, 169, 185, 101, 131, 253, 186, 219, 89, 9, 184, 62, 37, 101, 87, 149, 14, 214, 184, 32, 7, 8, 110, 157, 141}, {42, 239, 135, 195, 81, 125, 136, 127, 58, 211, 123, 157, 75, 107, 154, 100, 161, 46, 157, 58, 123, 179, 20, 189, 215, 98, 69, 18, 175, 20, 175, 11, 27, 127, 17, 177, 82, 77, 58, 140, 53, 23, 43, 11, 64, 33, 1, 163, 115, 59, 46, 114, 185, 216, 43, 233, 30, 109}, {187, 107, 37, 79, 138, 135, 199, 125, 100, 160, 209, 101, 79, 175, 142, 182, 14, 16, 33, 85, 179, 136, 192, 221, 110, 59, 128, 190, 176, 114, 107, 181, 8, 123, 87, 3, 82, 100, 79, 166, 32, 172, 206, 166, 177, 16, 30, 27, 156, 47, 3, 241, 186, 3, 233, 75, 189, 170}, {9, 165, 153, 194, 5, 174, 10, 63, 16, 164, 181, 18, 107, 155, 255, 189, 32, 70, 255, 198, 172, 116, 102, 163, 87, 238, 208, 19, 207, 81, 226, 130, 36, 223, 98, 234, 108, 136, 113, 176, 188, 113, 103, 29, 43, 131, 26, 247, 17, 208, 158, 247, 22, 55, 98, 62, 83, 91}, {122, 218, 243, 230, 181, 240, 78, 230, 125, 90, 141, 63, 181, 72, 34, 163, 211, 215, 3, 128, 106, 59, 113, 131, 158, 208, 182, 227, 2, 45, 162, 58, 49, 199, 209, 30, 40, 232, 161, 64, 126, 69, 193, 153, 253, 55, 57, 194, 77, 251, 139, 85, 136, 246, 82, 129, 112, 108}, {3, 23, 252, 210, 151, 185, 126, 184, 72, 131, 93, 160, 61, 246, 134, 64, 40, 203, 79, 34, 204, 149, 25, 221, 12, 193, 154, 85, 73, 152, 29, 129, 176, 161, 171, 238, 217, 105, 239, 86, 255, 10, 209, 131, 23, 37, 231, 26, 18, 135, 175, 22, 116, 6, 51, 194, 87, 235}, {19, 239, 7, 48, 105, 219, 196, 193, 243, 116, 95, 221, 73, 66, 231, 53, 8, 176, 139, 131, 2, 10, 74, 187, 90, 36, 199, 11, 209, 224, 181, 56, 51, 115, 183, 217, 134, 79, 181, 170, 252, 113, 6, 84, 254, 59, 138, 194, 181, 204, 63, 218, 218, 9, 135, 240, 75, 4}, {118, 105, 33, 252, 158, 172, 57, 215, 1, 102, 65, 97, 114, 123, 228, 46, 77, 159, 175, 112, 2, 78, 135, 37, 128, 188, 73, 95, 136, 97, 211, 225, 153, 170, 208, 55, 32, 27, 122, 127, 162, 200, 171, 237, 182, 165, 230, 222, 31, 80, 218, 186, 33, 56, 95, 30, 193, 34}, {6, 172, 37, 99, 30, 134, 173, 200, 150, 224, 104, 27, 101, 244, 250, 32, 37, 125, 178, 237, 232, 225, 10, 194, 38, 62, 40, 146, 22, 161, 1, 149, 232, 164, 114, 174, 164, 162, 21, 137, 28, 74, 253, 47, 236, 27, 24, 160, 99, 150, 248, 253, 248, 32, 175, 98, 175, 234}, {154, 136, 227, 53, 140, 76, 189, 152, 149, 52, 191, 42, 247, 51, 3, 188, 168, 129, 92, 162, 115, 60, 107, 187, 143, 17, 137, 157, 10, 219, 244, 253, 107, 94, 92, 239, 184, 30, 253, 86, 145, 64, 57, 221, 20, 1, 97, 228, 218, 81, 172, 106, 237, 195, 218, 25, 49, 20}, {14, 142, 223, 89, 178, 180, 186, 230, 37, 21, 217, 61, 213, 111, 83, 33, 88, 216, 192, 230, 12, 2, 136, 41, 188, 132, 163, 107, 195, 180, 59, 177, 232, 241, 187, 138, 165, 223, 243, 87, 177, 4, 57, 80, 43, 195, 13, 36, 232, 89, 143, 255, 208, 27, 118, 64, 9, 126}, {193, 156, 18, 104, 103, 145, 238, 163, 191, 245, 62, 77, 72, 18, 51, 35, 37, 30, 146, 119, 195, 104, 116, 164, 199, 215, 62, 107, 216, 252, 56, 249, 1, 107, 215, 213, 171, 23, 244, 94, 53, 209, 109, 74, 10, 103, 70, 207, 161, 94, 58, 155, 72, 138, 79, 245, 90, 130}, {79, 59, 250, 36, 207, 70, 246, 222, 60, 177, 165, 41, 204, 234, 152, 167, 149, 103, 155, 164, 187, 3, 17, 106, 13, 56, 133, 163, 235, 220, 120, 143, 129, 186, 95, 61, 175, 136, 71, 10, 115, 67, 117, 1, 45, 98, 49, 241, 153, 52, 208, 110, 173, 47, 113, 244, 61, 144}, {251, 48, 41, 161, 98, 4, 23, 58, 118, 137, 248, 53, 112, 216, 84, 215, 230, 30, 47, 192, 128, 172, 163, 224, 153, 32, 247, 171, 185, 250, 215, 122, 108, 176, 103, 100, 88, 226, 193, 41, 242, 37, 192, 195, 80, 138, 188, 51, 47, 149, 155, 136, 53, 252, 19, 64, 193, 142}, {124, 242, 42, 20, 52, 143, 229, 10, 57, 221, 174, 40, 150, 213, 224, 204, 178, 33, 118, 18, 244, 244, 237, 3, 222, 160, 236, 31, 243, 114, 105, 73, 192, 178, 102, 101, 53, 94, 197, 3, 132, 227, 160, 186, 34, 225, 141, 34, 52, 76, 102, 119, 181, 212, 14, 205, 191, 213}, {18, 64, 11, 249, 128, 124, 136, 8, 208, 164, 247, 53, 52, 35, 117, 134, 253, 34, 226, 165, 253, 103, 53, 43, 10, 195, 107, 215, 253, 44, 79, 166, 118, 115, 128, 1, 187, 156, 116, 38, 55, 38, 104, 27, 189, 70, 245, 66, 54, 172, 51, 147, 164, 178, 22, 189, 253, 110}, {186, 131, 99, 220, 159, 82, 188, 47, 130, 235, 80, 242, 18, 26, 119, 140, 149, 68, 174, 53, 227, 91, 10, 152, 118, 211, 236, 58, 19, 86, 67, 191, 40, 102, 127, 135, 84, 178, 104, 78, 20, 130, 120, 219, 219, 165, 194, 5, 198, 44, 83, 108, 68, 100, 192, 6, 80, 203}, {244, 1, 47, 157, 50, 104, 143, 121, 171, 22, 185, 89, 161, 84, 117, 207, 80, 102, 206, 80, 112, 208, 81, 221, 226, 101, 99, 138, 24, 202, 173, 238, 196, 243, 122, 135, 30, 65, 224, 10, 207, 251, 255, 153, 6, 227, 204, 111, 108, 15, 154, 216, 146, 153, 174, 27, 154, 46}, {166, 77, 140, 145, 232, 144, 89, 158, 148, 141, 37, 165, 157, 162, 192, 200, 9, 9, 104, 112, 87, 52, 200, 120, 142, 45, 51, 235, 242, 210, 120, 215, 74, 253, 40, 204, 70, 217, 114, 147, 235, 77, 87, 158, 168, 173, 127, 182, 243, 109, 81, 99, 102, 163, 156, 151, 214, 50}, {235, 88, 105, 58, 29, 99, 50, 220, 211, 227, 31, 24, 23, 181, 195, 94, 74, 2, 153, 222, 56, 121, 105, 55, 131, 212, 174, 111, 223, 208, 196, 124, 12, 40, 90, 94, 6, 220, 75, 174, 126, 71, 86, 38, 60, 251, 12, 123, 23, 235, 46, 225, 213, 196, 219, 254, 253, 173}, {167, 130, 60, 200, 96, 187, 40, 113, 160, 84, 38, 24, 41, 222, 144, 171, 225, 27, 143, 56, 22, 41, 127, 36, 234, 121, 79, 140, 113, 99, 114, 84, 85, 69, 215, 249, 41, 254, 25, 158, 209, 208, 108, 9, 109, 223, 220, 156, 92, 80, 114, 87, 64, 158, 130, 146, 138, 215}, {108, 47, 174, 236, 151, 205, 169, 124, 151, 201, 168, 91, 80, 176, 57, 217, 13, 166, 171, 95, 96, 91, 149, 209, 18, 164, 249, 213, 250, 137, 237, 234, 214, 216, 233, 152, 7, 248, 2, 105, 38, 58, 205, 209, 27, 40, 167, 68, 228, 43, 79, 118, 135, 82, 40, 15, 50, 86}, {41, 109, 177, 142, 47, 51, 187, 195, 198, 206, 119, 44, 158, 252, 67, 181, 212, 88, 228, 139, 126, 213, 82, 234, 75, 124, 215, 142, 248, 125, 35, 8, 11, 167, 53, 206, 180, 110, 70, 132, 89, 158, 220, 141, 167, 220, 220, 66, 176, 128, 95, 118, 86, 241, 187, 89, 169, 89}, {19, 197, 125, 125, 53, 99, 78, 4, 136, 250, 18, 247, 197, 225, 237, 240, 253, 76, 24, 40, 171, 184, 10, 240, 109, 99, 122, 70, 10, 81, 80, 6, 186, 200, 177, 71, 166, 34, 178, 3, 46, 215, 146, 89, 240, 139, 115, 249, 237, 110, 56, 42, 186, 43, 112, 120, 208, 250}, {76, 132, 133, 106, 171, 24, 138, 136, 53, 120, 173, 40, 116, 36, 165, 27, 205, 167, 81, 15, 168, 148, 227, 184, 214, 205, 123, 4, 108, 148, 229, 196, 244, 145, 144, 100, 250, 196, 117, 187, 145, 44, 231, 188, 176, 64, 13, 231, 127, 178, 180, 241, 61, 83, 21, 91, 102, 129}, {48, 210, 222, 175, 41, 107, 16, 81, 186, 110, 8, 71, 8, 48, 88, 203, 67, 80, 210, 123, 187, 227, 142, 241, 160, 79, 25, 237, 118, 57, 179, 239, 140, 1, 31, 71, 136, 158, 180, 190, 132, 130, 153, 179, 180, 177, 193, 7, 102, 67, 155, 145, 219, 53, 159, 224, 186, 35}, {42, 92, 106, 223, 29, 129, 147, 140, 69, 29, 215, 161, 128, 231, 13, 182, 77, 14, 138, 211, 22, 241, 200, 93, 228, 145, 118, 141, 106, 107, 163, 117, 132, 109, 128, 7, 172, 160, 39, 197, 49, 72, 240, 155, 75, 171, 149, 7, 35, 200, 99, 63, 144, 35, 25, 126, 144, 74}, {208, 233, 31, 47, 4, 122, 82, 145, 161, 246, 27, 245, 202, 177, 213, 121, 8, 131, 31, 207, 85, 30, 100, 142, 53, 205, 170, 102, 118, 16, 234, 141, 112, 36, 21, 182, 63, 246, 166, 158, 44, 135, 62, 122, 72, 187, 234, 187, 70, 199, 128, 31, 122, 67, 112, 185, 130, 81}}; auto rs = std::make_unique(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff, genmatrix); std::vector encoded_output = rs->encode_with_generator_matrix(information_vector); EXPECT_TRUE(code_vector == encoded_output); } TEST(ReedSolomonE1BTest, DecodeNoErrors) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; // Instantiate a ReedSolomon object with Galileo E1 (INAV) parameters const int nroots = 60; const int minpoly = 29; const int prim = 1; const int fcr = 195; const int pad = 0; const int shortening = 137; auto rs = std::make_unique(nroots, minpoly, prim, fcr, pad, shortening); int result = rs->decode(code_vector); EXPECT_TRUE(result == 0); std::vector decoded(code_vector.begin(), code_vector.begin() + 58); EXPECT_TRUE(information_vector == decoded); } TEST(ReedSolomonE1BTest, Decode30Errors) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; // Introduce 30 non-consecutive errors for (int i = 0; i < 60; i += 2) { code_vector[i] = 0; } auto rs = std::make_unique("E1B"); int result = rs->decode(code_vector); EXPECT_TRUE(result == 30); std::vector decoded(code_vector.begin(), code_vector.begin() + 58); EXPECT_TRUE(information_vector == decoded); } TEST(ReedSolomonE1BTest, Decode31Errors) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; // Introduce 31 errors (this should make the decoder to fail) for (int i = 0; i < 62; i += 2) { code_vector[i] = 0; } auto rs = std::make_unique("E1B"); int result = rs->decode(code_vector); EXPECT_TRUE(result == -1); } TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase1) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; std::vector erasure_positions; erasure_positions.reserve(60); // nroots is the maximum number of erasure positions // We have received Word 2, Word 4, Word 18, Word 20 // So we have: c_1, c_3, g_1, g_3 // Delete c_0 // We always know c_{0,0}, so we start at 1 for (int i = 1; i < 16; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete c_2 for (int i = 30; i < 44; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete g_0 for (int i = 58; i < 73; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137 } // Delete g_2 for (int i = 88; i < 103; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); } auto rs = std::make_unique("E1B"); int result = rs->decode(code_vector, erasure_positions); EXPECT_TRUE(result == 59); std::vector decoded(code_vector.begin(), code_vector.begin() + 58); EXPECT_TRUE(information_vector == decoded); } TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase2) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; std::vector erasure_positions; erasure_positions.reserve(60); // nroots is the maximum number of erasure positions // We have received Word 2, Word 4, Word 17, Word 19 // So we have: c_1, c_3, g_0, g_2 // Delete c_0 // We always know c_{0,0}, so we start at 1 for (int i = 1; i < 16; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete c_2 for (int i = 30; i < 44; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete g_1 for (int i = 73; i < 88; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137 } // Delete g_3 for (int i = 103; i < 118; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); } auto rs = std::make_unique("E1B"); int result = rs->decode(code_vector, erasure_positions); EXPECT_TRUE(result == 59); std::vector decoded(code_vector.begin(), code_vector.begin() + 58); EXPECT_TRUE(information_vector == decoded); } TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase3) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; std::vector erasure_positions; erasure_positions.reserve(60); // nroots is the maximum number of erasure positions // We have received Word 1, Word 3, Word 17, Word 19 // So we have: c_0, c_2, g_0, g_2 // Delete c_1 for (int i = 16; i < 30; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete c_3 for (int i = 44; i < 58; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete g_1 for (int i = 73; i < 88; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137 } // Delete g_3 for (int i = 103; i < 118; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); } auto rs = std::make_unique("E1B"); int result = rs->decode(code_vector, erasure_positions); EXPECT_TRUE(result == 58); std::vector decoded(code_vector.begin(), code_vector.begin() + 58); EXPECT_TRUE(information_vector == decoded); } TEST(ReedSolomonE1BTest, DecodeErasureCorrectionCase4) { // ICD 2.0 Annex F const std::vector information_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162}; std::vector code_vector = {147, 109, 66, 23, 234, 140, 74, 234, 49, 89, 241, 253, 169, 161, 89, 93, 75, 142, 83, 102, 98, 218, 14, 197, 155, 151, 43, 181, 9, 163, 142, 111, 8, 118, 21, 47, 135, 139, 108, 215, 51, 147, 185, 52, 17, 151, 97, 102, 238, 71, 83, 114, 47, 80, 67, 199, 215, 162, 238, 77, 12, 72, 235, 21, 148, 213, 230, 54, 183, 82, 49, 104, 12, 228, 150, 157, 220, 112, 236, 187, 63, 31, 175, 47, 210, 164, 17, 104, 98, 46, 252, 165, 194, 57, 26, 213, 14, 133, 176, 148, 34, 9, 167, 43, 204, 198, 25, 164, 233, 55, 153, 31, 237, 84, 212, 76, 137, 242}; std::vector erasure_positions; erasure_positions.reserve(60); // nroots is the maximum number of erasure positions // We have received Word 1, Word 3, Word 18, Word 20 // So we have: c_0, c_2, g_1, g_3 // Delete c_1 for (int i = 16; i < 30; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete c_3 for (int i = 44; i < 58; i++) { code_vector[i] = 0; erasure_positions.push_back(i); } // Delete g_0 for (int i = 58; i < 73; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); // erasure position refers to the unshortened code, so we add 137 } // Delete g_2 for (int i = 88; i < 103; i++) { code_vector[i] = 0; erasure_positions.push_back(i + 137); } auto rs = std::make_unique("E1B"); int result = rs->decode(code_vector, erasure_positions); EXPECT_TRUE(result == 58); std::vector decoded(code_vector.begin(), code_vector.begin() + 58); EXPECT_TRUE(information_vector == decoded); }