Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into pps_lime

This commit is contained in:
Javier Arribas 2021-04-07 14:52:59 +02:00
commit c1880d1ece
32 changed files with 2811 additions and 524 deletions

View File

@ -26,7 +26,7 @@ jobs:
steps:
- uses: actions/checkout@v1
- name: install dependencies
run: brew update && brew install ninja pkg-config hdf5 libtool automake armadillo lapack gflags glog gnuradio log4cpp pugixml protobuf && pip3 install mako
run: brew update && brew install ninja pkg-config hdf5 automake armadillo lapack gflags glog gnuradio log4cpp pugixml protobuf && pip3 install mako
- name: configure
run: cd build && cmake -GNinja ..
- name: build

View File

@ -326,13 +326,13 @@ set(GNSSSDR_PROTOBUF_MIN_VERSION "3.0.0")
################################################################################
set(GNSSSDR_GFLAGS_LOCAL_VERSION "2.2.2")
set(GNSSSDR_GLOG_LOCAL_VERSION "0.4.0")
set(GNSSSDR_ARMADILLO_LOCAL_VERSION "10.2.x")
set(GNSSSDR_ARMADILLO_LOCAL_VERSION "10.3.x")
set(GNSSSDR_GTEST_LOCAL_VERSION "1.10.0")
set(GNSSSDR_GNSS_SIM_LOCAL_VERSION "master")
set(GNSSSDR_GPSTK_LOCAL_VERSION "8.0.0")
set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.19")
set(GNSSSDR_MATIO_LOCAL_VERSION "1.5.21")
set(GNSSSDR_PUGIXML_LOCAL_VERSION "1.11.4")
set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.15.5")
set(GNSSSDR_PROTOCOLBUFFERS_LOCAL_VERSION "3.15.7")
set(GNSSSDR_BENCHMARK_LOCAL_VERSION "1.5.2")
set(GNSSSDR_MATHJAX_EXTERNAL_VERSION "2.7.7")
@ -2930,6 +2930,10 @@ if(GNURADIO_IIO_FOUND)
set(GR_IIO_INCLUDE_HAS_GNURADIO TRUE)
set(GNURADIO_API_IIO TRUE)
else()
# Force to always search for gr-iio
unset(GRIIO_FOUND CACHE)
unset(IIO_INCLUDE_DIRS CACHE)
unset(IIO_LIBRARIES CACHE)
find_package(GRIIO)
set_package_properties(GRIIO PROPERTIES
PURPOSE "Used for communication with PlutoSDR and FMCOMMS devices."

View File

@ -4,7 +4,7 @@ SPDX-License-Identifier: GPL-3.0-or-later
)
[comment]: # (
SPDX-FileCopyrightText: 2011-2020 Carles Fernandez-Prades <carles.fernandez@cttc.es>
SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc.es>
)
<!-- prettier-ignore-end -->
@ -12,7 +12,7 @@ SPDX-FileCopyrightText: 2011-2020 Carles Fernandez-Prades <carles.fernandez@cttc
[![License: GPL v3](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
[![REUSE status](https://api.reuse.software/badge/github.com/gnss-sdr/gnss-sdr)](https://api.reuse.software/info/github.com/gnss-sdr/gnss-sdr)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v2.0%20adopted-ff69b4.svg)](CODE_OF_CONDUCT.md)
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.0-4baaaa.svg)](CODE_OF_CONDUCT.md)
**Welcome to GNSS-SDR!**
@ -292,9 +292,9 @@ $ sudo apt-get install libblas-dev liblapack-dev # For Debian/Ubuntu/Linux
$ sudo yum install lapack-devel blas-devel # For Fedora/CentOS/RHEL
$ sudo zypper install lapack-devel blas-devel # For OpenSUSE
$ sudo pacman -S blas lapack # For Arch Linux
$ wget http://sourceforge.net/projects/arma/files/armadillo-10.2.1.tar.xz
$ tar xvfz armadillo-10.2.1.tar.xz
$ cd armadillo-10.2.1
$ wget http://sourceforge.net/projects/arma/files/armadillo-10.3.0.tar.xz
$ tar xvfz armadillo-10.3.0.tar.xz
$ cd armadillo-10.3.0
$ cmake .
$ make
$ sudo make install
@ -395,9 +395,9 @@ $ sudo apt-get install autoconf automake libtool curl make g++ unzip
and then:
```
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.5/protobuf-cpp-3.15.5.tar.gz
$ tar xvfz protobuf-cpp-3.15.5.tar.gz
$ cd protobuf-3.15.5
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v3.15.7/protobuf-cpp-3.15.7.tar.gz
$ tar xvfz protobuf-cpp-3.15.7.tar.gz
$ cd protobuf-3.15.7
$ ./autogen.sh
$ ./configure
$ make

View File

@ -12,7 +12,7 @@
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].
GNSS-SDR.internal_fs_sps=30000000
Receiver.sources_count=2
GNSS-SDR.num_sources=2
;######### CONTROL_THREAD CONFIG ############
ControlThread.wait_for_flowgraph=false

View File

@ -7,11 +7,11 @@
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
Receiver.sources_count=2
GNSS-SDR.num_sources=2
;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source
SignalSource0.filename=/archive/NT1065_L1_20160923_fs6625e6_if60e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource0.filename=../data/NT1065_L1_20160923_fs6625e6_if60e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource0.item_type=ibyte
SignalSource0.sampling_frequency=6625000
SignalSource0.samples=0
@ -19,7 +19,7 @@ SignalSource0.dump=false;
SignalSource0.dump_filename=/archive/signal_glonass.bin
SignalSource1.implementation=File_Signal_Source
SignalSource1.filename=/archive/NT1065_GLONASS_L1_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource1.filename=../data/NT1065_GLONASS_L1_20160923_fs6625e6_if0e3_schar.bin ; <- PUT YOUR FILE HERE
SignalSource1.item_type=ibyte
SignalSource1.sampling_frequency=6625000
SignalSource1.samples=0

View File

@ -7,7 +7,7 @@
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
Receiver.sources_count=2
GNSS-SDR.num_sources=2
;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source

View File

@ -1,4 +1,4 @@
; This is a GNSS-SDR configuration file
GNSS-SDR.num_sources; This is a GNSS-SDR configuration file
; The configuration API is described at https://gnss-sdr.org/docs/sp-blocks/
; SPDX-License-Identifier: GPL-3.0-or-later
; SPDX-FileCopyrightText: (C) 2010-2020 (see AUTHORS file for a list of contributors)
@ -7,7 +7,7 @@
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
Receiver.sources_count=2
GNSS-SDR.num_sources=2
;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source

View File

@ -7,7 +7,7 @@
;######### GLOBAL OPTIONS ##################
GNSS-SDR.internal_fs_sps=6625000
Receiver.sources_count=2
GNSS-SDR.num_sources=2
;######### SIGNAL_SOURCE CONFIG ############
SignalSource0.implementation=File_Signal_Source

View File

@ -13,7 +13,7 @@
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].
GNSS-SDR.internal_fs_sps=4000000
Receiver.sources_count=2
GNSS-SDR.num_sources=2
SignalSource.enable_throttle_control=false
SignalSource.repeat=false

View File

@ -9,7 +9,7 @@
[GNSS-SDR]
Receiver.sources_count=2
GNSS-SDR.num_sources=2
;######### GLOBAL OPTIONS ##################
;internal_fs_sps: Internal signal sampling frequency after the signal conditioning stage [samples per second].

View File

@ -63,7 +63,11 @@ SPDX-FileCopyrightText: 2011-2021 Carles Fernandez-Prades <carles.fernandez@cttc
- Fix bug that made the Monitor block to always set to 0 the
`carrier_phase_rads` parameter value.
- The `Labsat_Signal_Source` implementation of the `SignalSource` block now can
read files in the LabSat 3 Wideband format (`.LS3W`).
read files in the LabSat 3 Wideband format (`.LS3W`). When using this format,
this source block can provide multiple RF chain outputs.
- Replace `Receiver.sources_count` configuration parameter name by
`GNSS-SDR.num_sources`. The former parameter name is still read to ensure
backward compatibility with configuration files using that nomenclature.
&nbsp;

View File

@ -24,6 +24,7 @@
#include "galileo_almanac.h"
#include "galileo_almanac_helper.h"
#include "galileo_ephemeris.h"
#include "galileo_has_data.h"
#include "galileo_iono.h"
#include "galileo_utc_model.h"
#include "geojson_printer.h"
@ -503,6 +504,7 @@ rtklib_pvt_gs::rtklib_pvt_gs(uint32_t nchannels,
d_galileo_utc_model_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Utc_Model>).hash_code();
d_galileo_almanac_helper_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Almanac_Helper>).hash_code();
d_galileo_almanac_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_Almanac>).hash_code();
d_galileo_has_message_sptr_type_hash_code = typeid(std::shared_ptr<Galileo_HAS_data>).hash_code();
d_glonass_gnav_ephemeris_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Ephemeris>).hash_code();
d_glonass_gnav_utc_model_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Utc_Model>).hash_code();
d_glonass_gnav_almanac_sptr_type_hash_code = typeid(std::shared_ptr<Glonass_Gnav_Almanac>).hash_code();
@ -1318,6 +1320,10 @@ void rtklib_pvt_gs::msg_handler_telemetry(const pmt::pmt_t& msg)
d_user_pvt_solver->galileo_almanac_map[galileo_alm->PRN] = *galileo_alm;
}
}
else if (msg_type_hash_code == d_galileo_has_message_sptr_type_hash_code)
{
// Store HAS message and print its content
}
// **************** GLONASS GNAV Telemetry *************************
else if (msg_type_hash_code == d_glonass_gnav_ephemeris_sptr_type_hash_code)

View File

@ -216,6 +216,7 @@ private:
size_t d_galileo_utc_model_sptr_type_hash_code;
size_t d_galileo_almanac_helper_sptr_type_hash_code;
size_t d_galileo_almanac_sptr_type_hash_code;
size_t d_galileo_has_message_sptr_type_hash_code;
size_t d_glonass_gnav_ephemeris_sptr_type_hash_code;
size_t d_glonass_gnav_utc_model_sptr_type_hash_code;
size_t d_glonass_gnav_almanac_sptr_type_hash_code;

View File

@ -103,22 +103,6 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
const int l1_band = configuration->property("Channels_1C.count", 0) +
configuration->property("Channels_1B.count", 0);
// by default the DMA transfers samples corresponding to two frequency bands to the FPGA
num_freq_bands_ = 2;
dma_buff_offset_pos_ = 0;
// if only one input file is specified in the configuration file then:
// if there is at least one channel assigned to frequency band 1 then the DMA transfers the samples to the L1 frequency band channels
// otherwise the DMA transfers the samples to the L2/L5 frequency band channels
if (filename1.empty())
{
num_freq_bands_ = 1;
if (l1_band != 0)
{
dma_buff_offset_pos_ = 2;
}
}
const double default_seconds_to_skip = 0.0;
const std::string empty_string;
@ -140,6 +124,27 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(const ConfigurationInterface *con
filename1 = configuration->property(role + ".filename1", empty_string);
}
// by default the DMA transfers samples corresponding to two frequency bands to the FPGA
num_freq_bands_ = 2;
dma_buff_offset_pos_ = 0;
// if only one input file is specified in the configuration file then:
// if there is at least one channel assigned to frequency band 1 then the DMA transfers the samples to the L1 frequency band channels
// otherwise the DMA transfers the samples to the L2/L5 frequency band channels
// if more than one input file are specified then the DMA transfer the samples to both the L1 and the L2/L5 frequency channels.
if (filename1.empty())
{
num_freq_bands_ = 1;
if (l1_band != 0)
{
dma_buff_offset_pos_ = 2;
}
}
else
{
dma_buff_offset_pos_ = 2;
}
samples_ = configuration->property(role + ".samples", static_cast<int64_t>(0));
const double seconds_to_skip = configuration->property(role + ".seconds_to_skip", default_seconds_to_skip);
@ -649,6 +654,7 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0, const
// run the DMA
while (run_DMA)
{
dma_index = 0;
if (nbytes_remaining < read_buffer_size)
{
read_buffer_size = nbytes_remaining;
@ -684,26 +690,26 @@ void Ad9361FpgaSignalSource::run_DMA_process(const std::string &filename0, const
}
// read filename 1 (if enabled)
dma_index = 0;
if (num_freq_bands_ > 1)
{
dma_index = 0;
try
{
infile1.read(reinterpret_cast<char *>(input_samples.data()), read_buffer_size);
infile2.read(reinterpret_cast<char *>(input_samples.data()), read_buffer_size);
}
catch (const std::ifstream::failure &e)
{
std::cerr << "Exception reading file " << filename1 << '\n';
break;
}
if (infile1)
if (infile2)
{
nread_elements = read_buffer_size;
}
else
{
// FLAG AS ERROR !! IT SHOULD NEVER HAPPEN
nread_elements = infile1.gcount();
nread_elements = infile2.gcount();
}
for (int index0 = 0; index0 < (nread_elements); index0 += 2)

View File

@ -331,6 +331,15 @@ Fmcomms2SignalSource::Fmcomms2SignalSource(const ConfigurationInterface *configu
file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str());
DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")";
}
if (in_stream_ > 0)
{
LOG(ERROR) << "A signal source does not have an input stream";
}
if (out_stream_ > 1)
{
LOG(ERROR) << "This implementation only supports one output stream";
}
}

View File

@ -1,6 +1,6 @@
/*!
* \file labsat_signal_source.cc
* \brief Labsat 2 and 3 front-end signal sampler driver
* \brief LabSat version 2, 3, and 3 Wideband format reader
* \author Javier Arribas, jarribas(at)cttc.es
*
* -----------------------------------------------------------------------------
@ -8,7 +8,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -19,6 +19,8 @@
#include "gnss_sdr_string_literals.h"
#include "labsat23_source.h"
#include <glog/logging.h>
#include <iostream>
#include <sstream>
using namespace std::string_literals;
@ -37,7 +39,25 @@ LabsatSignalSource::LabsatSignalSource(const ConfigurationInterface* configurati
const int64_t sampling_frequency_deprecated = configuration->property(role + ".sampling_frequency", static_cast<int64_t>(16368000));
const int64_t throttle_frequency_sps = configuration->property(role + ".throttle_frequency_sps", static_cast<int64_t>(sampling_frequency_deprecated));
const int channel_selector = configuration->property(role + ".selected_channel", 1);
std::string channels_to_read = configuration->property(role + ".selected_channel", default_item_type);
std::stringstream ss(channels_to_read);
int found;
while (ss.good())
{
std::string substr;
getline(ss, substr, ',');
if (std::stringstream(substr) >> found)
{
if (found >= 1 && found <= 3)
{
channels_selector_vec_.push_back(found);
}
}
}
if (channels_selector_vec_.empty())
{
channels_selector_vec_.push_back(1);
}
const std::string default_filename("./example_capture.LS3");
filename_ = configuration->property(role + ".filename", default_filename);
@ -47,7 +67,7 @@ LabsatSignalSource::LabsatSignalSource(const ConfigurationInterface* configurati
if (item_type_ == "gr_complex")
{
item_size_ = sizeof(gr_complex);
labsat23_source_ = labsat23_make_source_sptr(filename_.c_str(), channel_selector, queue, digital_io_enabled);
labsat23_source_ = labsat23_make_source_sptr(filename_.c_str(), channels_selector_vec_, queue, digital_io_enabled);
DLOG(INFO) << "Item size " << item_size_;
DLOG(INFO) << "labsat23_source_(" << labsat23_source_->unique_id() << ")";
}
@ -58,49 +78,95 @@ LabsatSignalSource::LabsatSignalSource(const ConfigurationInterface* configurati
}
if (dump_)
{
DLOG(INFO) << "Dumping output into file " << dump_filename_;
DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")";
file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str());
std::vector<std::string> dump_filename;
file_sink_.reserve(channels_selector_vec_.size());
for (int i : channels_selector_vec_)
{
if (channels_selector_vec_.size() == 1)
{
dump_filename.push_back(dump_filename_);
}
else
{
std::string aux(dump_filename_.substr(0, dump_filename_.length() - 4));
std::string extension(dump_filename_.substr(dump_filename_.length() - 3, dump_filename_.length()));
if (i == 1)
{
aux += "_chA."s;
}
if (i == 2)
{
aux += "_chB."s;
}
if (i == 3)
{
aux += "_chC."s;
}
dump_filename.push_back(aux + extension);
}
std::cout << "Dumping output into file " << dump_filename.back() << '\n';
file_sink_.push_back(gr::blocks::file_sink::make(item_size_, dump_filename.back().c_str()));
DLOG(INFO) << "file_sink(" << file_sink_.back()->unique_id() << ")";
}
}
if (enable_throttle_control_)
{
throttle_ = gr::blocks::throttle::make(item_size_, throttle_frequency_sps);
for (auto it = channels_selector_vec_.begin(); it != channels_selector_vec_.end(); ++it)
{
throttle_.push_back(gr::blocks::throttle::make(item_size_, throttle_frequency_sps));
}
}
if (in_stream_ > 0)
{
LOG(ERROR) << "A signal source does not have an input stream";
}
if (out_stream_ > 1)
if (out_stream_ > 3)
{
LOG(ERROR) << "This implementation only supports one output stream";
LOG(ERROR) << "This implementation supports up to 3 output streams";
}
}
size_t LabsatSignalSource::getRfChannels() const
{
return channels_selector_vec_.size();
}
void LabsatSignalSource::connect(gr::top_block_sptr top_block)
{
if (enable_throttle_control_ == true)
{
top_block->connect(labsat23_source_, 0, throttle_, 0);
DLOG(INFO) << "connected labsat23_source_ to throttle";
if (dump_)
int rf_chan = 0;
for (const auto& th : throttle_)
{
top_block->connect(labsat23_source_, 0, file_sink_, 0);
DLOG(INFO) << "connected labsat23_source_to sink";
top_block->connect(labsat23_source_, rf_chan, th, 0);
DLOG(INFO) << "connected labsat23_source_ to throttle";
if (dump_)
{
top_block->connect(labsat23_source_, rf_chan, file_sink_[rf_chan], 0);
DLOG(INFO) << "connected labsat23_source_to sink";
}
rf_chan++;
}
}
else
{
if (dump_)
int rf_chan = 0;
for (auto it = channels_selector_vec_.begin(); it != channels_selector_vec_.end(); ++it)
{
top_block->connect(labsat23_source_, 0, file_sink_, 0);
DLOG(INFO) << "connected labsat23_source_ to sink";
}
else
{
DLOG(INFO) << "nothing to connect internally";
if (dump_)
{
top_block->connect(labsat23_source_, 0, file_sink_[rf_chan], 0);
DLOG(INFO) << "connected labsat23_source_ to sink";
}
else
{
DLOG(INFO) << "nothing to connect internally";
}
rf_chan++;
}
}
}
@ -110,20 +176,30 @@ void LabsatSignalSource::disconnect(gr::top_block_sptr top_block)
{
if (enable_throttle_control_ == true)
{
top_block->disconnect(labsat23_source_, 0, throttle_, 0);
DLOG(INFO) << "disconnected labsat23_source_ to throttle";
if (dump_)
int rf_chan = 0;
for (const auto& th : throttle_)
{
top_block->disconnect(labsat23_source_, 0, file_sink_, 0);
DLOG(INFO) << "disconnected labsat23_source_ to sink";
top_block->disconnect(labsat23_source_, rf_chan, th, 0);
DLOG(INFO) << "disconnected labsat23_source_ to throttle";
if (dump_)
{
top_block->disconnect(labsat23_source_, rf_chan, file_sink_[rf_chan], 0);
DLOG(INFO) << "disconnected labsat23_source_ to sink";
}
rf_chan++;
}
}
else
{
if (dump_)
int rf_chan = 0;
for (auto it = channels_selector_vec_.begin(); it != channels_selector_vec_.end(); ++it)
{
top_block->disconnect(labsat23_source_, 0, file_sink_, 0);
DLOG(INFO) << "disconnected labsat23_source_ to sink";
if (dump_)
{
top_block->disconnect(labsat23_source_, rf_chan, file_sink_[rf_chan], 0);
DLOG(INFO) << "disconnected labsat23_source_ to sink";
}
rf_chan++;
}
}
}
@ -140,7 +216,17 @@ gr::basic_block_sptr LabsatSignalSource::get_right_block()
{
if (enable_throttle_control_ == true)
{
return throttle_;
return throttle_[0];
}
return labsat23_source_;
}
gr::basic_block_sptr LabsatSignalSource::get_right_block(int i)
{
if (enable_throttle_control_ == true)
{
return throttle_[i];
}
return labsat23_source_;
}

View File

@ -1,6 +1,6 @@
/*!
* \file labsat_signal_source.h
* \brief Labsat 2 and 3 front-end signal sampler driver
* \brief LabSat version 2, 3, and 3 Wideband format reader
* \author Javier Arribas, jarribas(at)cttc.es
*
* -----------------------------------------------------------------------------
@ -8,7 +8,7 @@
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
* This file is part of GNSS-SDR.
*
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -27,6 +27,7 @@
#include <pmt/pmt.h>
#include <memory>
#include <string>
#include <vector>
/** \addtogroup Signal_Source
* \{ */
@ -37,7 +38,8 @@
class ConfigurationInterface;
/*!
* \brief This class reads samples stored by a LabSat 2 or LabSat 3 device
* \brief This class reads samples stored in LabSat version 2, 3, and 3 Wideband
* format.
*/
class LabsatSignalSource : public SignalSourceBase
{
@ -53,15 +55,18 @@ public:
return item_size_;
}
size_t getRfChannels() const override;
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
gr::basic_block_sptr get_right_block(int i) override;
private:
gr::block_sptr labsat23_source_;
gr::blocks::file_sink::sptr file_sink_;
gr::blocks::throttle::sptr throttle_;
std::vector<gr::blocks::file_sink::sptr> file_sink_;
std::vector<gr::blocks::throttle::sptr> throttle_;
std::vector<int> channels_selector_vec_;
std::string item_type_;
std::string filename_;

View File

@ -1,7 +1,7 @@
/*!
* \file labsat23_source.h
*
* \brief Unpacks capture files in the Labsat 2 (ls2), Labsat 3 (ls3), or Labsat
* \brief Unpacks capture files in the LabSat 2 (ls2), LabSat 3 (ls3), or LabSat
* 3 Wideband (LS3W) formats.
* \author Javier Arribas jarribas (at) cttc.es
*
@ -23,9 +23,11 @@
#include "gnss_block_interface.h"
#include <gnuradio/block.h>
#include <pmt/pmt.h>
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <string>
#include <vector>
/** \addtogroup Signal_Source
* \{ */
@ -39,12 +41,13 @@ using labsat23_source_sptr = gnss_shared_ptr<labsat23_source>;
labsat23_source_sptr labsat23_make_source_sptr(
const char *signal_file_basename,
int channel_selector,
const std::vector<int> &channel_selector,
Concurrent_Queue<pmt::pmt_t> *queue,
bool digital_io_enabled);
/*!
* \brief This class implements conversion between Labsat2 and 3 format byte packet samples to gr_complex
* \brief This class implements conversion between Labsat 2, 3 and 3 Wideband
* formats to gr_complex
*/
class labsat23_source : public gr::block
{
@ -59,28 +62,29 @@ public:
private:
friend labsat23_source_sptr labsat23_make_source_sptr(
const char *signal_file_basename,
int channel_selector,
const std::vector<int> &channel_selector,
Concurrent_Queue<pmt::pmt_t> *queue,
bool digital_io_enabled);
labsat23_source(const char *signal_file_basename,
int channel_selector,
const std::vector<int> &channel_selector,
Concurrent_Queue<pmt::pmt_t> *queue,
bool digital_io_enabled);
std::string generate_filename();
int parse_header();
int getBit(uint8_t byte, int position);
int read_ls3w_ini(const std::string &filename);
int number_of_samples_per_ls3w_register() const;
void decode_samples_one_channel(int16_t input_short, gr_complex *out, int type);
void decode_ls3w_register_one_channel(uint64_t input, gr_complex *out) const;
void decode_ls3w_register(uint64_t input, std::vector<gr_complex *> &out, std::size_t output_pointer) const;
std::ifstream binary_input_file;
std::string d_signal_file_basename;
Concurrent_Queue<pmt::pmt_t> *d_queue;
int d_channel_selector_config;
std::vector<int> d_channel_selector_config;
int d_current_file_number;
uint8_t d_labsat_version;
uint8_t d_channel_selector;
@ -90,6 +94,7 @@ private:
// Data members for Labsat 3 Wideband
std::string d_ls3w_OSC;
std::vector<int> d_ls3w_selected_channel_offset;
int64_t d_ls3w_SMP{};
int32_t d_ls3w_QUA{};
int32_t d_ls3w_CHN{};
@ -101,7 +106,6 @@ private:
int32_t d_ls3w_BWB{};
int32_t d_ls3w_BWC{};
int d_ls3w_spare_bits{};
int d_ls3w_selected_channel_offset{};
int d_ls3w_samples_per_register{};
bool d_is_ls3w = false;
bool d_ls3w_digital_io_enabled = false;

View File

@ -26,6 +26,7 @@
#include "display.h"
#include "galileo_almanac_helper.h" // for Galileo_Almanac_Helper
#include "galileo_ephemeris.h" // for Galileo_Ephemeris
#include "galileo_has_data.h" // For Galileo HAS messages
#include "galileo_iono.h" // for Galileo_Iono
#include "galileo_utc_model.h" // for Galileo_Utc_Model
#include "gnss_synchro.h"
@ -512,15 +513,15 @@ void galileo_telemetry_decoder_gs::decode_CNAV_word(float *page_symbols, int32_t
// 4. If we have a new full message, read it
if (d_cnav_nav.have_new_HAS_message() == true)
{
// TODO: Retrieve data from message and send it somewhere
// Galileo_HAS_data has_data = d_cnav_nav.get_HAS_data();
if (d_cnav_nav.is_HAS_message_dummy())
if (d_cnav_nav.is_HAS_message_dummy() == true)
{
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS dummy message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
}
else
{
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS dummy message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
const std::shared_ptr<Galileo_HAS_data> tmp_obj = std::make_shared<Galileo_HAS_data>(d_cnav_nav.get_HAS_data());
this->message_port_pub(pmt::mp("telemetry"), pmt::make_any(tmp_obj));
std::cout << TEXT_MAGENTA << "New Galileo E6 HAS message received in channel " << d_channel << " from satellite " << d_satellite << TEXT_RESET << '\n';
}
}
}
@ -649,7 +650,7 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
if (abs(corr_value) >= d_samples_per_preamble)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
DLOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite;
LOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite << " in channel " << this->d_channel;
d_stat = 1; // enter into frame pre-detection status
}
}

View File

@ -91,24 +91,23 @@ ControlThread::ControlThread()
const std::string empty_implementation;
std::string src_impl = configuration_->property("SignalSource.implementation", empty_implementation);
int src_count = configuration_->property("Receiver.sources_count", 1);
if (src_impl.empty() && (src_count != 1))
int src_count_deprecated = configuration_->property("Receiver.sources_count", 1);
int src_count = configuration_->property("GNSS-SDR.num_sources", src_count_deprecated);
if (src_impl.empty())
{
src_impl = std::string("");
int num_src = 0;
for (int i = 0; i < src_count; i++)
for (auto i = 0; i < src_count; i++)
{
std::string src_impl_multiple = configuration_->property("SignalSource" + std::to_string(i) + ".implementation", empty_implementation);
if (!src_impl_multiple.empty())
{
num_src++;
}
}
if (num_src != src_count)
{
src_impl = std::string("");
auto src_impl_multiple = configuration_->property("SignalSource" + std::to_string(i) + ".implementation", empty_implementation);
num_src += !src_impl_multiple.empty();
}
conf_has_signal_sources_ = (num_src == src_count);
}
else
{
conf_has_signal_sources_ = true;
}
conf_has_signal_sources_ = !src_impl.empty();
std::string pvt_impl = configuration_->property("PVT.implementation", empty_implementation);
conf_has_pvt_ = !pvt_impl.empty();

View File

@ -22,6 +22,7 @@
#include "file_configuration.h"
#include "gnss_sdr_make_unique.h"
#include <glog/logging.h>
#include <iostream>
#include <utility>
@ -55,7 +56,7 @@ void FileConfiguration::init()
}
else
{
LOG(WARNING) << "Unable to open configuration file " << filename_;
std::cerr << "Unable to open configuration file " << filename_ << '\n';
}
}

View File

@ -100,7 +100,8 @@ void GNSSFlowgraph::init()
channels_status_ = channel_status_msg_receiver_make();
// 1. read the number of RF front-ends available (one file_source per RF front-end)
sources_count_ = configuration_->property("Receiver.sources_count", 1);
int sources_count_deprecated = configuration_->property("Receiver.sources_count", 1);
sources_count_ = configuration_->property("GNSS-SDR.num_sources", sources_count_deprecated);
int signal_conditioner_ID = 0;
@ -112,7 +113,10 @@ void GNSSFlowgraph::init()
{
auto& src = sig_source_.back();
auto RF_Channels = src->getRfChannels();
std::cout << "RF Channels: " << RF_Channels << '\n';
if (sources_count_ == 1)
{
std::cout << "RF Channels: " << RF_Channels << '\n';
}
for (auto j = 0U; j < RF_Channels; ++j)
{
sig_conditioner_.push_back(block_factory->GetSignalConditioner(configuration_.get(), signal_conditioner_ID));
@ -120,6 +124,10 @@ void GNSSFlowgraph::init()
}
}
}
if (sources_count_ != 1 && !enable_fpga_offloading_)
{
std::cout << "RF Channels: " << sources_count_ << '\n';
}
if (!sig_conditioner_.empty())
{
signal_conditioner_connected_ = std::vector<bool>(sig_conditioner_.size(), false);
@ -522,7 +530,6 @@ int GNSSFlowgraph::disconnect_desktop_flowgraph()
int GNSSFlowgraph::connect_fpga_flowgraph()
{
// Check that the Signal Source has been instantiated successfully
for (auto& src : sig_source_)
{
if (src == nullptr)
@ -541,7 +548,6 @@ int GNSSFlowgraph::connect_fpga_flowgraph()
}
// Connect blocks to the top_block
if (connect_channels() != 0)
{
return 1;
@ -560,7 +566,6 @@ int GNSSFlowgraph::connect_fpga_flowgraph()
DLOG(INFO) << "Blocks connected internally to the top_block";
// Connect the counter
if (connect_fpga_sample_counter() != 0)
{
return 1;

View File

@ -24,6 +24,7 @@ set(SYSTEM_PARAMETERS_SOURCES
glonass_gnav_ephemeris.cc
glonass_gnav_utc_model.cc
glonass_gnav_navigation_message.cc
reed_solomon.cc
)
set(SYSTEM_PARAMETERS_HEADERS
@ -82,6 +83,7 @@ set(SYSTEM_PARAMETERS_HEADERS
Beidou_B3I.h
Beidou_DNAV.h
MATH_CONSTANTS.h
reed_solomon.h
)
list(SORT SYSTEM_PARAMETERS_HEADERS)

View File

@ -68,14 +68,16 @@ constexpr int32_t GALILEO_CNAV_CRC_LENGTH = 24;
constexpr int32_t GALILEO_CNAV_MESSAGE_BITS_PER_PAGE = 424;
constexpr int32_t GALILEO_CNAV_PAGE_HEADER_BITS = 24;
constexpr int32_t GALILEO_CNAV_PREAMBLE_LENGTH_BITS = 16;
constexpr int32_t GALILEO_CNAV_MAX_NUMBER_ENCODED_BLOCKS = 255;
constexpr int32_t GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK = 255;
constexpr int32_t GALILEO_CNAV_MT1_HEADER_BITS = 32;
constexpr int32_t GALILEO_CNAV_OCTETS_IN_SUBPAGE = 53;
constexpr int32_t GALILEO_CNAV_INFORMATION_VECTOR_LENGTH = 32;
constexpr int32_t HAS_MSG_MAX_SATS = 40;
constexpr int32_t HAS_MSG_MAX_SIGNALS = 16;
constexpr uint8_t HAS_MSG_GPS_SYSTEM = 0; // Table 8 ICD
constexpr uint8_t HAS_MSG_GALILEO_SYSTEM = 2; // Table 8 ICD
constexpr uint8_t HAS_MSG_GPS_SYSTEM = 0; // Table 8 ICD v1.2
constexpr uint8_t HAS_MSG_GALILEO_SYSTEM = 2; // Table 8 ICD v1.2
constexpr char GALILEO_CNAV_PREAMBLE[17] = "1011011101110000";

View File

@ -3,14 +3,14 @@
* \brief Implementation of a Galileo CNAV Data message as described in
* Galileo High Accuracy Service E6-B Signal-In-Space Message Specification v1.2
* (April 2020)
* \author Carles Fernandez-Prades, 2020 cfernandez(at)cttc.es
* \author Carles Fernandez-Prades, 2020-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-2020 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -60,10 +60,11 @@ void Galileo_Cnav_Message::read_HAS_page(const std::string& page_string)
if (CRC_test(Word_for_CRC_bits, checksum.to_ulong()) == true)
{
d_flag_CRC_test = true;
// CRC correct: Read HAS page header
// CRC correct: Read 24 bits of HAS page header
read_HAS_page_header(page_string.substr(GALILEO_CNAV_PAGE_RESERVED_BITS, GALILEO_CNAV_PAGE_HEADER_BITS));
bool use_has = false;
d_test_mode = false;
// HAS status as defined in ICD v1.2 Table 5 HAS Page Header
switch (d_has_page_status)
{
case 0: // HAS is in Test Mode
@ -73,11 +74,14 @@ void Galileo_Cnav_Message::read_HAS_page(const std::string& page_string)
case 1: // HAS is in Operational Mode
use_has = true;
break;
case 2: // HAS is in "reserved" status
case 3: // Do not use HAS
default:
break;
}
if (use_has)
{
// Process the 424 bits of encoded data
process_HAS_page(page_string.substr(GALILEO_CNAV_PAGE_RESERVED_BITS + GALILEO_CNAV_PAGE_HEADER_BITS, GALILEO_CNAV_MESSAGE_BITS_PER_PAGE));
}
}
@ -101,11 +105,12 @@ void Galileo_Cnav_Message::read_HAS_page_header(const std::string& page_string)
}
if (!d_page_dummy)
{
// ICD v1.2 Table 5: HAS page header
const std::bitset<GALILEO_CNAV_PAGE_HEADER_BITS> has_page_header(page_string);
d_has_page_status = read_has_page_header_parameter(has_page_header, GALILEO_HAS_STATUS);
d_received_message_type = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_TYPE);
d_received_message_id = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_ID);
d_received_message_size = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_SIZE);
d_received_message_size = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_SIZE) + 1; // "0" means 1
d_received_message_page_id = read_has_page_header_parameter(has_page_header, GALILEO_HAS_MESSAGE_PAGE_ID);
}
}
@ -116,14 +121,27 @@ void Galileo_Cnav_Message::process_HAS_page(const std::string& page_string)
if (d_current_message_id == d_received_message_id)
{
// if receiver pid was not there, store it.
if (std::find(d_list_pid.begin(), d_list_pid.end(), d_received_message_page_id) == d_list_pid.end())
if (d_received_message_page_id == 0)
{
if (d_received_message_type == 1) // contains satellite corrections
// reserved, ignore it
}
else
{
if (std::find(d_list_pid.begin(), d_list_pid.end(), d_received_message_page_id) == d_list_pid.end())
{
d_received_encoded_messages++;
d_list_pid.push_back(d_received_message_page_id);
// Store encoded page
d_encoded_message_type_1 += std::string(page_string);
if (d_received_message_type == 1) // contains satellite corrections
{
d_received_encoded_messages++;
d_list_pid.push_back(d_received_message_page_id);
// Pack encoded string into 53 octets and put it in
// the corresponding row of d_C_matrix.
for (int k = 0; k < GALILEO_CNAV_OCTETS_IN_SUBPAGE; k++)
{
std::string bits8 = page_string.substr(k * 8, 8);
std::bitset<8> bs(bits8);
d_C_matrix[d_received_message_page_id - 1][k] = static_cast<uint8_t>(bs.to_ulong());
}
}
}
}
}
@ -134,48 +152,112 @@ void Galileo_Cnav_Message::process_HAS_page(const std::string& page_string)
d_received_encoded_messages = 0;
d_new_message = false;
d_current_message_size = d_received_message_size;
// erase stored pages and start storing again
d_encoded_message_type_1.clear();
// erase stored pages and data, and start storing again
d_list_pid.clear();
d_HAS_data = Galileo_HAS_data();
if (d_received_message_type == 1)
{
d_encoded_message_type_1.reserve(GALILEO_CNAV_MAX_NUMBER_ENCODED_BLOCKS * GALILEO_CNAV_MESSAGE_BITS_PER_PAGE);
d_received_encoded_messages++;
d_list_pid.push_back(d_received_message_page_id);
d_encoded_message_type_1 += std::string(page_string);
// Pack encoded string into 53 octets and put it in
// the corresponding row of d_C_matrix.
for (int k = 0; k < GALILEO_CNAV_OCTETS_IN_SUBPAGE; k++)
{
std::string bits8 = page_string.substr(k * 8, 8);
std::bitset<8> bs(bits8);
d_C_matrix[d_received_message_page_id - 1][k] = static_cast<uint8_t>(bs.to_ulong());
}
}
}
if (d_received_encoded_messages == d_current_message_size)
{
// we have a full encoded message stored in d_encoded_message_type_1
// we have a full encoded message stored in d_C_matrix
d_received_encoded_messages = 0;
d_current_message_id = 0;
d_new_message = true;
decode_message_type1();
int res = decode_message_type1();
if (res == 0)
{
d_new_message = true;
}
else
{
d_new_message = false;
}
}
}
void Galileo_Cnav_Message::decode_message_type1()
int Galileo_Cnav_Message::decode_message_type1()
{
// TODO: Reed-Solomon decoding of d_encoded_message_type_1
// TODO: reordering
// decoded_message_type1 = ...
// read_HAS_message_type1(decoded_message_type1);
}
// All rows in d_C_matrix with no data are erasure positions
std::vector<int> erasure_positions;
erasure_positions.reserve(GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK - d_list_pid.size());
for (int mpid = 1; mpid <= GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK; mpid++)
{
if (std::find(d_list_pid.begin(), d_list_pid.end(), static_cast<uint8_t>(mpid)) == d_list_pid.end())
{
erasure_positions.push_back(static_cast<uint8_t>(mpid - 1));
}
else
{
d_list_pid.remove(static_cast<uint8_t>(mpid));
}
}
void Galileo_Cnav_Message::read_HAS_message_type1(const std::string& message_string)
{
d_HAS_data = Galileo_HAS_data();
read_MT1_header(message_string);
read_MT1_body(message_string);
// Vertical decoding of d_C_matrix
for (int col = 0; col < GALILEO_CNAV_OCTETS_IN_SUBPAGE; col++)
{
std::vector<uint8_t> C_column(GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, 0);
for (int row = 0; row < GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK; row++)
{
C_column[row] = d_C_matrix[row][col];
}
int result = rs.decode(C_column, erasure_positions);
if (result < 0)
{
// Decoding failed
d_C_matrix = {GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)};
d_M_matrix = {GALILEO_CNAV_INFORMATION_VECTOR_LENGTH, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE)};
return -1;
}
std::vector<uint8_t> M_column(C_column.begin(), C_column.begin() + GALILEO_CNAV_INFORMATION_VECTOR_LENGTH);
for (int i = 0; i < GALILEO_CNAV_INFORMATION_VECTOR_LENGTH; i++)
{
d_M_matrix[i][col] = M_column[i];
}
}
// Form the decoded HAS message by reading rows of d_M_matrix
std::string decoded_message_type_1;
decoded_message_type_1.reserve(d_current_message_size * GALILEO_CNAV_OCTETS_IN_SUBPAGE * 8);
for (uint8_t row = 0; row < d_current_message_size; row++)
{
for (int col = 0; col < GALILEO_CNAV_OCTETS_IN_SUBPAGE; col++)
{
std::bitset<8> bs(d_M_matrix[row][col]);
decoded_message_type_1 += bs.to_string();
}
}
// reset d_C_matrix and d_M_matrix for next decoding
d_C_matrix = {GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)};
d_M_matrix = {GALILEO_CNAV_INFORMATION_VECTOR_LENGTH, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)};
// Trigger HAS message content reading
read_MT1_header(decoded_message_type_1);
read_MT1_body(decoded_message_type_1);
return 0;
}
void Galileo_Cnav_Message::read_MT1_header(const std::string& message_string)
{
// ICD v1.2 Table 6: MT1 Message Header.
const std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> has_mt1_header(message_string);
d_HAS_data.header.toh = read_has_message_header_parameter_uint16(has_mt1_header, GALILEO_MT1_HEADER_TOH);
d_HAS_data.header.mask_id = read_has_message_header_parameter_uint8(has_mt1_header, GALILEO_MT1_HEADER_MASK_ID);
@ -192,6 +274,7 @@ void Galileo_Cnav_Message::read_MT1_header(const std::string& message_string)
void Galileo_Cnav_Message::read_MT1_body(const std::string& message_string)
{
// ICD v1.2 Table 7: MT1 Message Body.
auto message = std::string(message_string.begin() + GALILEO_CNAV_MT1_HEADER_BITS, message_string.end()); // Remove header
int Nsat = 0;
if (d_HAS_data.header.mask_flag)

View File

@ -3,14 +3,14 @@
* \brief Implementation of a Galileo CNAV Data message as described in
* Galileo High Accuracy Service E6-B Signal-In-Space Message Specification v1.2
* (April 2020)
* \author Carles Fernandez-Prades, 2020 cfernandez(at)cttc.es
* \author Carles Fernandez-Prades, 2020-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-2020 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2021 (see AUTHORS file for a list of contributors)
* SPDX-License-Identifier: GPL-3.0-or-later
*
* -----------------------------------------------------------------------------
@ -21,10 +21,12 @@
#include "Galileo_CNAV.h"
#include "galileo_has_data.h"
#include "reed_solomon.h"
#include <bitset>
#include <cstdint>
#include <list>
#include <string>
#include <vector>
/** \addtogroup Core
* \{ */
@ -68,23 +70,24 @@ private:
bool CRC_test(std::bitset<GALILEO_CNAV_BITS_FOR_CRC> bits, uint32_t checksum) const;
void read_HAS_page_header(const std::string& page_string);
void process_HAS_page(const std::string& page_string);
void decode_message_type1();
void read_HAS_message_type1(const std::string& message_string);
void read_MT1_header(const std::string& message_string);
void read_MT1_body(const std::string& message_string);
int decode_message_type1();
uint8_t read_has_page_header_parameter(std::bitset<GALILEO_CNAV_PAGE_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
uint8_t read_has_message_header_parameter_uint8(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
uint16_t read_has_message_header_parameter_uint16(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
bool read_has_message_header_parameter_bool(std::bitset<GALILEO_CNAV_MT1_HEADER_BITS> bits, const std::pair<int32_t, int32_t>& parameter) const;
uint8_t read_has_message_body_uint8(const std::string& bits) const;
uint16_t read_has_message_body_uint16(const std::string& bits) const;
uint64_t read_has_message_body_uint64(const std::string& bits) const;
int16_t read_has_message_body_int16(const std::string& bits) const;
Galileo_HAS_data d_HAS_data{};
std::string d_encoded_message_type_1;
ReedSolomon rs = ReedSolomon();
std::vector<std::vector<uint8_t>> d_C_matrix{GALILEO_CNAV_MAX_NUMBER_SYMBOLS_ENCODED_BLOCK, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)}; // 255 x 53
std::vector<std::vector<uint8_t>> d_M_matrix{GALILEO_CNAV_INFORMATION_VECTOR_LENGTH, std::vector<uint8_t>(GALILEO_CNAV_OCTETS_IN_SUBPAGE, 0)}; // 32 x 53
std::list<uint8_t> d_list_pid;
uint8_t d_has_page_status{};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
/*!
* \file reed_solomon.h
* \brief Class implementing a Reed-Solomon encoder/decoder for blocks of 255
* symbols and symbols of 8 bits.
* \author Carles Fernandez, 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
*
* -----------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_REED_SOLOMON_H
#define GNSS_SDR_REED_SOLOMON_H
#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>
/** \addtogroup Core
* \{ */
/** \addtogroup System_Parameters
* \{ */
/*!
* \brief
* Class implementing a Reed-Solomon encoder and decoder RS(255,K,d) where
* k=255-nroots is the information vector length and d=nroots+1 is the minimum
* Hamming distance, with symbols of 8 bits. It allows shortened RS codes.
*/
class ReedSolomon
{
public:
/*!
* \brief Default constructor.
* Constructs a Reed Solomon object. The encode_with_generator_poly
* and encode_with_generator_matrix methods are available for testing
* purposes.
*
* gnss_signal: empty or "E6B" sets the Galileo E6B RS parameters.
* "E1B" sets the Galileo E1B (INAV) RS parameters.
*/
explicit ReedSolomon(const std::string& gnss_signal = std::string());
/*!
* \brief Custom constructor for RS(255, 255-nroots, nroots+1). Parameters:
*
* nroots - the number of roots in the RS code generator polynomial,
* which is the same as the number of parity symbols in a block.
*
* minpoly - primitive polynomial.
*
* prim - the primitive root of the generator polynomial.
*
* fcr - first consecutive root of the Reed-Solomon generator polynomial.
*
* pad - the number of pad symbols in a block. If not defined, it defaults
* to 0.
*
* shortening - value of the shortening parameter. Defaults to 0.
* If different to 0, it defines a shortened RS encoder/decoder.
*
* genpoly_coeff - a vector of (nroots+1) elements containing the generator
* polynomial coefficients. Only used for encoding. Defaults to empty.
* If defined, the encode_with_generator_poly method can be used.
*
* gen_matrix - a (255-shortening)x(255-nroots-shortening) matrix containing
* the elements of the generator matrix. Only used for encoding. Defaults
* to empty. If defined, the encode_with_generator_matrix method can be
* used.
*/
ReedSolomon(int nroots,
int minpoly,
int prim,
int fcr,
int pad = 0,
int shortening = 0,
const std::vector<uint8_t>& genpoly_coeff = std::vector<uint8_t>{},
const std::vector<std::vector<uint8_t>>& gen_matrix = std::vector<std::vector<uint8_t>>{});
/*!
* \brief Decode an encoded block.
*
* The decoded symbols are at the first 255-nroots-shortening elements
* of the data_to_decode vector.
*
* The second parameter is optional, and contains a vector of erasure
* positions to be passed to the decoding algorithm. Defaults to empty.
*
* Returns the number of corrected errors, or -1 if decoding failed.
*/
int decode(std::vector<uint8_t>& data_to_decode,
const std::vector<int>& erasure_positions = std::vector<int>{}) const;
/*!
* \brief Encode data with the generator matrix (for testing purposes)
*
* Returns the encoded vector. It is set to all zeros if the generator
* matrix is not defined.
*/
std::vector<uint8_t> encode_with_generator_matrix(const std::vector<uint8_t>& data_to_encode) const;
/*!
* \brief Encode data with the generator polynomial (for testing purposes)
*
* Returns the encoded vector. It is set to all zeros if the generator
* polynomial is not defined.
*/
std::vector<uint8_t> encode_with_generator_poly(const std::vector<uint8_t>& data_to_encode) const;
private:
static const int d_symbols_per_block = 255; // the total number of symbols in a RS block.
static const int d_symsize = 8; // symbol size, in bits.
int mod255(int x) const;
int rs_min(int a, int b) const;
int decode_rs_8(uint8_t* data, const int* eras_pos, int no_eras) const;
uint8_t galois_mul(uint8_t a, uint8_t b) const;
uint8_t galois_add(uint8_t a, uint8_t b) const;
uint8_t galois_mul_table(uint8_t a, uint8_t b) const;
void encode_rs_8(const uint8_t* data, uint8_t* parity) const;
void init_log_tables(); // initialize d_log_table and d_antilog
void init_alpha_tables(); // initialize d_alpha_to, d_index_of
std::array<uint8_t, 256> d_alpha_to{}; // used for decoding
std::array<uint8_t, 256> d_index_of{}; // used for decoding
std::array<uint8_t, 256> d_log_table{}; // used for encoding
std::array<uint8_t, 255> d_antilog{}; // used for encoding
std::vector<std::vector<uint8_t>> d_genmatrix; // used for encoding
std::vector<uint8_t> d_genpoly_coeff; // used for encoding
std::vector<uint8_t> d_genpoly_index; // used for encoding
size_t d_data_in_block{}; // number of information symbols in a block
size_t d_rows_G{}; // number of rows of the generator matrix
size_t d_columns_G{}; // number of rows of the generator matrix
size_t d_info_symbols_shortened{}; // number of info symbols in the shortened code
size_t d_data_symbols_shortened{}; // number of data symbols in the shortened code
int d_nroots{}; // number of parity symbols in a block
int d_prim{}; // The primitive root of the generator poly
int d_pad{}; // the number of pad symbols in a block
int d_iprim{}; // prim-th root of 1, index form
int d_fcr{}; // first consecutive root
int d_shortening{}; // shortening parameter
uint8_t d_min_poly{}; // primitive polynomial
uint8_t d_a0{}; // auxiliar variable
};
/** \} */
/** \} */
#endif // GNSS_SDR_REED_SOLOMON_H

View File

@ -126,6 +126,8 @@ DECLARE_string(log_dir);
#include "unit-tests/signal-processing-blocks/pvt/rtcm_test.cc"
#include "unit-tests/signal-processing-blocks/pvt/serdes_monitor_pvt_test.cc"
#include "unit-tests/signal-processing-blocks/telemetry_decoder/galileo_fnav_inav_decoder_test.cc"
#include "unit-tests/system-parameters/galileo_e1b_reed_solomon_test.cc"
#include "unit-tests/system-parameters/galileo_e6b_reed_solomon_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_crc_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc"
#include "unit-tests/system-parameters/glonass_gnav_nav_message_test.cc"

View File

@ -0,0 +1,310 @@
/*!
* \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 <gtest/gtest.h>
TEST(ReedSolomonE1BTest, EncodeWithPoly)
{
const std::vector<uint8_t> 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<uint8_t> 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<ReedSolomon>("E1B");
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<uint8_t> 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<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff);
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<ReedSolomon>("E1B");
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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 = 1;
const int pad = 0;
const int shortening = 137;
const std::vector<uint8_t> genpoly_coeff;
const std::vector<std::vector<uint8_t>> 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<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff, genmatrix);
std::vector<uint8_t> 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<uint8_t> 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<uint8_t> 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<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening);
int result = rs->decode(code_vector);
EXPECT_TRUE(result == 0);
std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);
EXPECT_TRUE(information_vector == decoded);
}
TEST(ReedSolomonE1BTest, Decode30Errors)
{
// ICD 2.0 Annex F
const std::vector<uint8_t> 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<uint8_t> 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<ReedSolomon>("E1B");
int result = rs->decode(code_vector);
EXPECT_TRUE(result == 30);
std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);
EXPECT_TRUE(information_vector == decoded);
}
TEST(ReedSolomonE1BTest, Decode31Errors)
{
// ICD 2.0 Annex F
const std::vector<uint8_t> 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<uint8_t> 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<ReedSolomon>("E1B");
int result = rs->decode(code_vector);
EXPECT_TRUE(result == -1);
}
TEST(ReedSolomonE1BTest, Decode33ErrorsWithErasure)
{
// ICD 2.0 Annex F
const std::vector<uint8_t> 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<uint8_t> 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 33 errors
for (int i = 0; i < 66; i += 2)
{
code_vector[i] = 0;
}
std::vector<int> erasure_positions{2, 4, 16, 18, 22, 54};
auto rs = std::make_unique<ReedSolomon>("E1B");
int result = rs->decode(code_vector, erasure_positions);
EXPECT_TRUE(result == 33);
std::vector<uint8_t> decoded(code_vector.begin(), code_vector.begin() + 58);
EXPECT_TRUE(information_vector == decoded);
}

View File

@ -0,0 +1,519 @@
/*!
* \file galileo_e6b_reed_solomon_test.cc
* \brief Tests for Reed Solomon E6B 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 <gtest/gtest.h>
TEST(ReedSolomonE6BTest, EncodeWithGenMatrix)
{
// input vector as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> input = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
// Expected encoded output as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> expected_output = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
auto rs = std::make_unique<ReedSolomon>();
std::vector<uint8_t> encoded_output = rs->encode_with_generator_matrix(input);
EXPECT_TRUE(encoded_output == expected_output);
}
TEST(ReedSolomonE6BTest, EncodeWithGenPoly)
{
// input vector as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> input = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
// Expected encoded output as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> expected_output = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
auto rs = std::make_unique<ReedSolomon>();
std::vector<uint8_t> encoded_output = rs->encode_with_generator_poly(input);
EXPECT_TRUE(encoded_output == expected_output);
}
TEST(ReedSolomonE6BTest, EncodeWithCustomPoly)
{
// input vector as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> input = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
// Expected encoded output as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> expected_output = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
const int nroots = 223;
const int minpoly = 29;
const int prim = 1;
const int fcr = 1;
const int pad = 0;
const int shortening = 0;
const std::vector<uint8_t> genpoly_coeff = {88, 216, 195, 23, 111, 82, 79, 81, 62, 120, 249, 250, 11, 134, 209, 116, 69, 170, 208, 45, 249, 223, 4, 19, 120, 81, 182, 217, 44, 65, 93, 34, 118, 227, 112, 28, 65, 48, 244, 165, 242, 216, 121, 50, 171, 32, 217, 166, 133, 134, 4, 120, 54, 42, 13, 24, 95, 228, 173, 247, 80, 42, 89, 68, 81, 181, 112, 51, 118, 108, 243, 223, 18, 38, 230, 1, 28, 109, 131, 14, 234, 151, 21, 108, 7, 176, 236, 147, 175, 183, 66, 35, 178, 243, 36, 115, 255, 51, 36, 6, 120, 163, 59, 9, 214, 102, 109, 253, 152, 137, 1, 144, 124, 241, 143, 71, 91, 227, 28, 174, 13, 157, 78, 20, 192, 64, 130, 45, 39, 46, 229, 171, 193, 252, 43, 165, 88, 180, 179, 183, 88, 99, 219, 52, 210, 33, 160, 146, 22, 255, 111, 159, 7, 237, 145, 194, 68, 89, 231, 201, 224, 127, 5, 27, 112, 71, 165, 204, 236, 122, 119, 49, 212, 216, 151, 149, 53, 249, 57, 136, 85, 14, 19, 128, 135, 177, 179, 189, 164, 98, 220, 99, 241, 230, 188, 170, 148, 97, 121, 31, 253, 134, 43, 199, 81, 137, 82, 54, 47, 216, 172, 169, 123, 246, 153, 169, 32, 86, 128, 83, 5, 252, 251, 1};
auto rs = std::make_unique<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff);
std::vector<uint8_t> encoded_output = rs->encode_with_generator_poly(input);
EXPECT_TRUE(encoded_output == expected_output);
}
TEST(ReedSolomonE6BTest, EncodeWithCustomMatrix)
{
// input vector as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> input = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
// Expected encoded output as defined in Galileo HAS ICD v1.2, Annex D
const std::vector<uint8_t> expected_output = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
const int nroots = 223;
const int minpoly = 29;
const int prim = 1;
const int fcr = 1;
const int pad = 0;
const int shortening = 0;
const std::vector<uint8_t> genpoly_coeff;
const std::vector<std::vector<uint8_t>> 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 1},
{19, 143, 180, 59, 221, 29, 49, 45, 231, 9, 73, 73, 159, 2, 158, 136, 212, 218, 14, 113, 215, 20, 187, 55, 137, 181, 203, 113, 97, 135, 14, 251},
{27, 27, 1, 50, 255, 109, 251, 156, 148, 151, 85, 21, 74, 116, 250, 77, 60, 203, 113, 196, 213, 23, 202, 125, 31, 252, 90, 1, 176, 226, 44, 252},
{98, 153, 190, 38, 223, 28, 28, 149, 170, 219, 41, 235, 236, 175, 113, 182, 239, 31, 74, 241, 127, 121, 207, 137, 205, 70, 88, 218, 250, 129, 99, 5},
{95, 235, 199, 105, 168, 182, 233, 133, 201, 135, 171, 89, 50, 230, 115, 227, 21, 122, 41, 226, 93, 59, 20, 36, 30, 150, 134, 240, 34, 91, 183, 83},
{172, 171, 163, 123, 27, 81, 14, 251, 24, 56, 15, 35, 244, 148, 24, 35, 96, 195, 47, 232, 148, 85, 117, 91, 39, 5, 74, 71, 104, 116, 14, 128},
{117, 108, 167, 111, 201, 61, 244, 13, 5, 236, 75, 124, 11, 233, 60, 127, 101, 117, 144, 13, 51, 70, 138, 247, 188, 171, 120, 104, 141, 220, 39, 86},
{243, 8, 122, 204, 147, 89, 112, 127, 204, 217, 20, 179, 8, 167, 203, 254, 95, 38, 22, 249, 215, 127, 101, 46, 99, 252, 183, 17, 8, 122, 191, 32},
{90, 195, 11, 73, 110, 20, 55, 185, 206, 241, 12, 193, 185, 72, 141, 27, 97, 29, 251, 144, 6, 109, 129, 203, 222, 64, 164, 49, 173, 37, 167, 169},
{164, 41, 177, 10, 34, 58, 123, 165, 122, 70, 108, 145, 240, 246, 208, 134, 248, 114, 237, 129, 149, 218, 70, 63, 105, 5, 184, 222, 9, 255, 213, 153},
{211, 255, 215, 20, 146, 60, 12, 202, 1, 95, 234, 192, 175, 223, 81, 99, 59, 136, 191, 82, 138, 174, 112, 1, 21, 14, 137, 7, 4, 238, 50, 246},
{220, 94, 230, 67, 248, 163, 186, 77, 68, 20, 1, 180, 150, 94, 127, 36, 154, 47, 101, 114, 172, 174, 172, 248, 130, 250, 55, 68, 17, 106, 3, 123},
{110, 20, 220, 172, 53, 110, 224, 20, 10, 192, 59, 46, 159, 96, 14, 203, 214, 144, 215, 141, 13, 190, 175, 232, 55, 123, 104, 223, 79, 38, 146, 169},
{164, 29, 102, 221, 199, 97, 1, 114, 215, 130, 93, 166, 31, 208, 248, 5, 40, 197, 96, 173, 136, 209, 149, 17, 74, 236, 131, 18, 231, 29, 214, 172},
{251, 94, 49, 176, 56, 250, 251, 10, 237, 114, 111, 176, 78, 90, 148, 97, 69, 174, 3, 178, 4, 16, 151, 192, 36, 202, 212, 81, 210, 20, 219, 216},
{116, 79, 18, 201, 172, 40, 33, 232, 54, 187, 32, 61, 5, 227, 55, 18, 43, 107, 202, 220, 141, 66, 224, 166, 158, 176, 61, 11, 143, 232, 112, 47},
{187, 194, 174, 69, 228, 144, 68, 94, 189, 124, 254, 101, 65, 91, 176, 76, 117, 203, 236, 169, 202, 251, 11, 110, 242, 80, 181, 94, 162, 92, 111, 54},
{29, 150, 209, 144, 66, 224, 111, 137, 81, 38, 230, 100, 15, 45, 7, 31, 208, 240, 210, 18, 111, 85, 199, 64, 247, 215, 164, 75, 231, 34, 69, 82},
{191, 102, 106, 86, 63, 166, 105, 80, 243, 169, 231, 39, 86, 171, 77, 223, 72, 220, 171, 98, 179, 115, 160, 191, 202, 89, 192, 20, 178, 54, 121, 137},
{254, 252, 23, 88, 159, 236, 167, 50, 34, 70, 225, 175, 28, 89, 25, 150, 163, 25, 241, 87, 152, 213, 166, 176, 237, 50, 249, 60, 144, 205, 27, 81},
{138, 9, 193, 221, 141, 92, 54, 239, 124, 193, 92, 251, 33, 190, 134, 68, 160, 220, 80, 210, 146, 184, 240, 135, 188, 129, 101, 218, 102, 213, 132, 199},
{184, 160, 40, 202, 31, 235, 178, 121, 225, 205, 231, 122, 61, 178, 191, 195, 55, 13, 2, 41, 245, 69, 128, 182, 5, 90, 7, 28, 79, 58, 11, 43},
{247, 8, 171, 147, 180, 87, 67, 121, 151, 143, 177, 155, 64, 107, 163, 222, 211, 152, 178, 184, 68, 211, 218, 210, 252, 37, 84, 189, 44, 186, 133, 134},
{31, 50, 155, 253, 213, 220, 84, 174, 239, 85, 87, 105, 214, 81, 160, 211, 90, 32, 239, 171, 171, 238, 177, 234, 36, 233, 216, 77, 44, 173, 205, 253},
{113, 18, 35, 135, 205, 43, 156, 23, 127, 169, 162, 160, 15, 49, 202, 100, 165, 163, 175, 30, 199, 19, 141, 197, 211, 200, 134, 41, 215, 154, 34, 31},
{204, 239, 127, 208, 89, 187, 30, 192, 37, 152, 221, 214, 211, 49, 93, 9, 93, 38, 25, 9, 6, 86, 219, 250, 25, 161, 185, 32, 98, 177, 32, 121},
{72, 7, 24, 67, 1, 245, 154, 234, 84, 179, 37, 96, 222, 33, 64, 228, 78, 254, 194, 19, 197, 60, 60, 241, 58, 151, 184, 179, 233, 70, 85, 97},
{253, 151, 182, 118, 101, 136, 118, 241, 195, 26, 152, 14, 225, 28, 193, 165, 140, 82, 138, 36, 216, 2, 152, 228, 117, 234, 180, 94, 11, 25, 50, 148},
{20, 35, 254, 1, 198, 250, 222, 43, 98, 131, 180, 54, 101, 212, 227, 212, 85, 247, 217, 50, 117, 7, 116, 145, 101, 136, 176, 12, 83, 1, 146, 170},
{145, 235, 144, 178, 16, 181, 198, 59, 220, 241, 197, 242, 187, 44, 243, 109, 86, 53, 21, 48, 83, 149, 252, 147, 181, 124, 48, 89, 151, 149, 227, 188},
{214, 115, 72, 209, 6, 224, 24, 39, 114, 233, 248, 204, 31, 222, 125, 2, 236, 241, 19, 132, 104, 150, 172, 254, 222, 170, 104, 161, 199, 252, 179, 230},
{241, 67, 229, 75, 108, 250, 81, 179, 127, 247, 83, 66, 159, 206, 107, 96, 58, 217, 252, 157, 139, 17, 235, 115, 5, 174, 191, 230, 233, 49, 241, 241},
{165, 246, 113, 208, 142, 14, 235, 211, 178, 85, 75, 239, 238, 96, 147, 129, 143, 18, 30, 123, 124, 195, 21, 230, 104, 198, 220, 56, 202, 53, 246, 99},
{219, 121, 50, 105, 81, 61, 239, 218, 41, 238, 236, 242, 77, 40, 161, 123, 92, 58, 122, 26, 3, 147, 12, 163, 109, 207, 110, 216, 66, 41, 93, 220},
{56, 105, 223, 38, 38, 53, 34, 72, 93, 91, 133, 135, 1, 232, 7, 61, 70, 61, 102, 124, 94, 21, 181, 225, 227, 23, 51, 104, 159, 94, 117, 98},
{200, 107, 25, 252, 122, 136, 229, 62, 85, 8, 171, 117, 186, 197, 183, 103, 52, 41, 91, 19, 211, 165, 97, 52, 227, 241, 116, 70, 115, 251, 56, 164},
{99, 62, 142, 10, 191, 175, 135, 155, 202, 184, 151, 52, 17, 239, 5, 26, 201, 44, 159, 38, 76, 235, 82, 145, 61, 162, 223, 9, 169, 204, 77, 189},
{197, 14, 41, 244, 99, 82, 51, 75, 53, 246, 248, 215, 70, 118, 32, 124, 79, 180, 4, 127, 169, 157, 105, 103, 85, 151, 125, 63, 246, 69, 228, 179},
{55, 161, 79, 12, 207, 40, 253, 100, 230, 119, 111, 97, 76, 61, 94, 122, 5, 74, 200, 112, 206, 160, 19, 75, 142, 167, 222, 9, 180, 99, 57, 177},
{17, 80, 149, 28, 144, 190, 229, 240, 26, 182, 124, 100, 217, 51, 52, 9, 182, 169, 42, 94, 114, 239, 69, 95, 173, 11, 101, 72, 64, 50, 3, 135},
{12, 91, 119, 248, 135, 229, 140, 37, 129, 209, 39, 237, 182, 202, 102, 204, 89, 159, 208, 66, 154, 204, 54, 66, 32, 13, 61, 13, 184, 70, 75, 128},
{117, 204, 87, 187, 74, 161, 64, 143, 219, 117, 162, 84, 197, 171, 98, 1, 138, 76, 204, 242, 153, 72, 19, 180, 165, 172, 112, 31, 199, 12, 21, 19},
{24, 225, 130, 141, 144, 160, 197, 221, 109, 80, 74, 157, 237, 227, 1, 143, 161, 216, 190, 28, 103, 248, 231, 29, 74, 248, 192, 160, 226, 203, 254, 14},
{242, 17, 183, 221, 223, 54, 147, 94, 222, 19, 137, 147, 116, 241, 4, 34, 163, 217, 140, 42, 34, 191, 244, 240, 48, 18, 110, 84, 212, 155, 159, 85},
{198, 3, 198, 145, 91, 104, 40, 111, 171, 25, 48, 170, 91, 222, 108, 67, 99, 147, 168, 118, 148, 82, 76, 9, 226, 178, 78, 148, 151, 183, 234, 136},
{237, 10, 198, 207, 133, 149, 88, 94, 250, 23, 24, 49, 14, 86, 242, 63, 235, 232, 176, 37, 91, 230, 60, 107, 210, 175, 217, 195, 113, 111, 148, 57},
{252, 70, 251, 156, 71, 58, 104, 35, 181, 22, 29, 18, 45, 124, 115, 246, 91, 204, 171, 171, 10, 8, 109, 87, 86, 26, 6, 194, 111, 15, 44, 249},
{61, 247, 189, 11, 255, 205, 190, 159, 73, 215, 216, 211, 50, 194, 165, 173, 247, 237, 123, 131, 188, 226, 189, 197, 112, 84, 126, 46, 193, 255, 184, 53},
{40, 156, 37, 206, 118, 220, 97, 4, 164, 201, 150, 153, 5, 88, 33, 143, 80, 1, 230, 22, 33, 31, 14, 175, 218, 151, 224, 19, 52, 213, 244, 149},
{7, 121, 65, 169, 163, 244, 187, 17, 112, 237, 46, 113, 109, 50, 57, 188, 171, 241, 132, 47, 144, 234, 210, 48, 167, 146, 6, 41, 127, 185, 80, 151},
{33, 85, 209, 187, 99, 27, 241, 145, 182, 43, 152, 91, 166, 94, 114, 169, 45, 163, 104, 175, 26, 115, 76, 130, 55, 152, 136, 45, 135, 225, 32, 216},
{116, 149, 25, 41, 167, 115, 192, 226, 173, 224, 121, 202, 238, 11, 51, 244, 227, 3, 199, 183, 144, 92, 131, 125, 220, 163, 111, 87, 243, 189, 133, 212},
{160, 202, 250, 200, 192, 43, 249, 18, 14, 151, 249, 96, 181, 91, 160, 155, 39, 28, 47, 110, 5, 38, 203, 203, 1, 103, 73, 198, 63, 163, 145, 49},
{100, 7, 242, 101, 230, 151, 67, 247, 146, 170, 239, 129, 240, 215, 250, 144, 17, 158, 47, 155, 183, 246, 28, 5, 202, 8, 216, 253, 69, 13, 144, 119},
{186, 166, 166, 145, 230, 236, 133, 44, 96, 122, 206, 139, 96, 30, 65, 96, 251, 202, 46, 177, 105, 85, 144, 33, 232, 28, 135, 70, 64, 24, 189, 122},
{125, 253, 144, 215, 58, 109, 158, 6, 140, 237, 28, 168, 63, 148, 208, 125, 70, 43, 60, 183, 25, 111, 239, 227, 103, 164, 69, 30, 44, 240, 238, 236},
{79, 231, 215, 32, 107, 20, 43, 26, 230, 83, 183, 70, 84, 250, 132, 244, 30, 68, 74, 255, 253, 232, 200, 251, 43, 161, 44, 134, 187, 133, 145, 204},
{21, 229, 206, 84, 62, 194, 60, 102, 75, 4, 220, 56, 176, 209, 192, 112, 8, 94, 248, 15, 74, 182, 177, 114, 195, 206, 113, 105, 159, 63, 57, 165},
{112, 108, 180, 230, 202, 246, 252, 111, 117, 175, 210, 10, 195, 231, 143, 229, 10, 202, 230, 244, 135, 102, 250, 118, 242, 55, 43, 125, 231, 167, 135, 71},
{205, 154, 65, 115, 150, 138, 189, 176, 159, 48, 250, 135, 228, 77, 78, 173, 208, 178, 71, 189, 8, 130, 129, 62, 19, 152, 204, 112, 34, 15, 42, 112},
{195, 133, 16, 131, 217, 207, 15, 17, 168, 72, 182, 124, 156, 4, 38, 75, 208, 55, 40, 147, 80, 134, 226, 57, 75, 233, 92, 24, 247, 205, 149, 27},
{128, 91, 2, 15, 14, 219, 62, 231, 152, 107, 5, 251, 73, 170, 42, 255, 5, 28, 181, 87, 240, 145, 152, 73, 251, 215, 147, 35, 202, 183, 79, 5},
{95, 9, 5, 213, 129, 103, 46, 167, 187, 181, 27, 117, 34, 67, 118, 184, 92, 144, 42, 29, 251, 180, 252, 115, 222, 160, 23, 59, 219, 107, 129, 127},
{34, 145, 97, 163, 240, 99, 224, 52, 91, 27, 163, 13, 24, 220, 81, 216, 61, 25, 80, 27, 25, 185, 99, 100, 162, 201, 57, 38, 169, 202, 171, 224},
{155, 178, 152, 248, 234, 66, 116, 165, 4, 232, 10, 178, 59, 197, 10, 91, 34, 238, 48, 229, 220, 24, 121, 14, 142, 75, 92, 140, 53, 106, 227, 201},
{74, 184, 197, 204, 104, 42, 159, 160, 168, 203, 23, 245, 157, 180, 35, 108, 4, 247, 100, 221, 252, 211, 44, 40, 161, 48, 91, 177, 109, 16, 224, 231},
{226, 80, 154, 253, 172, 137, 170, 25, 31, 36, 56, 228, 57, 78, 159, 182, 128, 235, 244, 155, 5, 145, 21, 196, 90, 100, 238, 164, 152, 28, 19, 89},
{18, 25, 164, 149, 142, 135, 198, 151, 60, 180, 76, 80, 230, 139, 21, 246, 110, 97, 210, 120, 168, 133, 5, 145, 244, 247, 37, 98, 209, 145, 37, 68},
{248, 116, 245, 46, 159, 233, 159, 253, 83, 98, 58, 194, 2, 110, 157, 178, 162, 165, 254, 26, 224, 145, 178, 152, 114, 92, 76, 237, 158, 173, 14, 194},
{231, 91, 11, 41, 98, 144, 242, 73, 175, 207, 52, 108, 221, 155, 179, 74, 98, 154, 77, 47, 145, 115, 196, 31, 141, 207, 26, 157, 128, 99, 69, 145},
{75, 176, 108, 107, 23, 148, 51, 54, 134, 194, 17, 234, 222, 226, 184, 52, 25, 140, 39, 93, 210, 10, 104, 38, 9, 43, 85, 10, 104, 43, 222, 237},
{92, 94, 46, 231, 10, 36, 227, 154, 49, 80, 209, 2, 137, 25, 108, 20, 131, 193, 227, 149, 192, 55, 22, 75, 103, 122, 104, 231, 206, 70, 68, 7},
{121, 214, 117, 143, 206, 89, 179, 32, 21, 14, 178, 51, 248, 135, 228, 243, 2, 191, 235, 169, 138, 172, 49, 147, 211, 75, 49, 34, 221, 124, 108, 159},
{185, 39, 183, 74, 227, 158, 201, 236, 236, 6, 9, 181, 104, 219, 67, 64, 140, 148, 86, 111, 106, 201, 187, 196, 168, 45, 71, 181, 163, 15, 149, 111},
{15, 111, 192, 134, 62, 204, 46, 57, 198, 220, 244, 251, 221, 182, 220, 133, 4, 232, 180, 36, 154, 117, 97, 116, 109, 32, 152, 53, 121, 42, 47, 255},
{87, 1, 11, 170, 17, 250, 238, 55, 59, 146, 185, 145, 190, 62, 12, 21, 70, 84, 123, 167, 251, 10, 125, 123, 66, 246, 196, 139, 109, 220, 185, 22},
{71, 74, 17, 6, 15, 146, 107, 234, 137, 157, 221, 246, 241, 146, 72, 115, 22, 129, 144, 3, 158, 222, 200, 152, 18, 68, 90, 188, 142, 192, 24, 146},
{126, 156, 188, 60, 66, 222, 98, 216, 17, 255, 152, 216, 248, 200, 14, 74, 65, 139, 46, 19, 154, 57, 21, 115, 8, 118, 158, 217, 234, 177, 111, 160},
{47, 142, 147, 67, 44, 227, 21, 168, 151, 216, 89, 62, 250, 165, 74, 185, 147, 22, 5, 138, 55, 242, 24, 57, 100, 167, 83, 58, 175, 115, 63, 33},
{73, 144, 57, 155, 60, 182, 188, 241, 254, 163, 68, 197, 171, 184, 17, 18, 242, 11, 197, 242, 162, 153, 183, 129, 64, 242, 52, 164, 231, 5, 160, 210},
{202, 242, 96, 114, 134, 254, 154, 128, 117, 242, 17, 246, 223, 18, 112, 174, 3, 235, 3, 87, 136, 108, 179, 77, 236, 98, 152, 166, 151, 130, 13, 52},
{59, 228, 148, 40, 210, 184, 99, 13, 92, 252, 250, 25, 191, 183, 111, 210, 135, 47, 238, 31, 34, 63, 59, 150, 219, 190, 29, 132, 221, 4, 135, 219},
{65, 3, 105, 33, 78, 229, 48, 7, 5, 17, 117, 115, 16, 20, 101, 108, 249, 218, 89, 162, 68, 88, 31, 83, 78, 141, 9, 81, 249, 115, 114, 99},
{219, 157, 199, 113, 160, 253, 4, 1, 253, 89, 168, 204, 209, 214, 213, 141, 177, 76, 178, 93, 218, 171, 151, 169, 216, 233, 37, 13, 43, 26, 27, 88},
{1, 175, 221, 243, 223, 150, 131, 20, 195, 95, 120, 137, 81, 97, 19, 52, 129, 138, 123, 79, 185, 78, 132, 36, 16, 192, 99, 216, 25, 165, 45, 183},
{123, 99, 4, 20, 155, 224, 253, 96, 2, 165, 255, 216, 84, 34, 11, 83, 58, 203, 206, 214, 133, 224, 22, 122, 211, 12, 130, 206, 202, 170, 225, 179},
{55, 31, 34, 33, 47, 208, 79, 170, 205, 64, 60, 102, 67, 47, 10, 81, 42, 63, 183, 186, 103, 140, 110, 52, 147, 33, 69, 246, 69, 95, 214, 180},
{78, 217, 117, 166, 51, 55, 232, 219, 136, 176, 59, 71, 7, 54, 250, 207, 62, 19, 105, 137, 20, 2, 4, 201, 69, 77, 35, 123, 71, 98, 9, 88},
{1, 58, 153, 65, 8, 5, 73, 248, 25, 42, 145, 26, 218, 183, 243, 27, 195, 5, 36, 148, 109, 128, 45, 183, 112, 93, 199, 222, 111, 201, 85, 165},
{112, 120, 107, 177, 223, 192, 59, 26, 235, 253, 252, 71, 225, 141, 233, 214, 97, 1, 189, 40, 28, 65, 204, 234, 55, 132, 184, 203, 80, 87, 113, 43},
{247, 192, 115, 208, 207, 151, 104, 240, 244, 133, 129, 128, 125, 183, 156, 136, 198, 206, 190, 7, 69, 58, 222, 158, 160, 23, 138, 2, 251, 165, 232, 252},
{98, 117, 101, 84, 61, 44, 230, 6, 198, 187, 59, 63, 121, 152, 178, 208, 42, 229, 79, 62, 188, 233, 226, 157, 46, 249, 179, 10, 249, 202, 36, 193},
{210, 77, 203, 244, 98, 21, 100, 71, 96, 65, 54, 182, 156, 230, 250, 224, 97, 97, 31, 13, 209, 19, 108, 22, 14, 81, 255, 241, 196, 144, 48, 171},
{130, 162, 74, 188, 56, 12, 24, 172, 87, 250, 78, 57, 164, 215, 95, 252, 182, 219, 141, 135, 187, 37, 83, 188, 187, 162, 34, 103, 11, 133, 124, 229},
{196, 155, 245, 4, 123, 227, 238, 196, 192, 201, 155, 47, 214, 115, 221, 199, 165, 240, 196, 144, 236, 254, 136, 213, 193, 9, 247, 63, 140, 105, 154, 46},
{168, 253, 206, 153, 244, 90, 190, 188, 118, 131, 197, 151, 204, 138, 190, 46, 116, 159, 121, 214, 81, 142, 12, 49, 8, 186, 199, 229, 247, 216, 224, 39},
{35, 18, 213, 92, 18, 32, 163, 180, 130, 116, 180, 242, 103, 130, 93, 241, 167, 10, 104, 181, 54, 135, 118, 39, 89, 7, 169, 11, 99, 104, 47, 45},
{157, 150, 134, 244, 214, 20, 46, 134, 50, 218, 163, 99, 173, 61, 240, 43, 35, 238, 145, 233, 16, 104, 165, 150, 124, 224, 137, 40, 96, 163, 243, 130},
{83, 94, 239, 60, 225, 202, 211, 119, 171, 212, 59, 66, 104, 180, 180, 154, 216, 159, 161, 81, 129, 234, 220, 73, 126, 135, 22, 73, 32, 199, 236, 64},
{180, 51, 88, 137, 101, 242, 22, 92, 8, 209, 99, 140, 86, 232, 224, 9, 185, 92, 56, 176, 178, 232, 11, 157, 180, 56, 55, 7, 44, 122, 96, 192},
{193, 20, 57, 242, 98, 80, 139, 154, 221, 134, 21, 167, 176, 203, 20, 58, 108, 40, 168, 11, 136, 9, 214, 200, 135, 126, 245, 4, 168, 194, 142, 20},
{97, 223, 113, 66, 240, 219, 163, 213, 247, 105, 91, 200, 228, 152, 156, 102, 140, 2, 240, 50, 129, 133, 160, 93, 174, 246, 89, 111, 195, 22, 26, 78},
{70, 8, 143, 72, 73, 69, 52, 183, 169, 243, 7, 53, 53, 120, 43, 2, 105, 112, 241, 117, 239, 48, 104, 246, 141, 176, 208, 220, 126, 224, 229, 157},
{159, 27, 28, 198, 131, 35, 183, 49, 168, 168, 102, 146, 77, 18, 157, 130, 200, 86, 133, 151, 5, 132, 76, 243, 194, 4, 55, 182, 159, 191, 21, 13},
{199, 26, 140, 14, 238, 2, 67, 91, 6, 205, 170, 100, 199, 87, 74, 59, 207, 195, 16, 130, 205, 225, 88, 2, 88, 88, 210, 48, 97, 114, 249, 174},
{221, 62, 67, 44, 76, 233, 250, 18, 23, 177, 178, 213, 175, 134, 50, 222, 206, 224, 25, 32, 152, 125, 204, 99, 56, 175, 235, 226, 50, 129, 168, 28},
{249, 207, 146, 253, 136, 29, 143, 209, 20, 235, 30, 29, 26, 151, 85, 116, 134, 62, 72, 44, 92, 53, 101, 226, 57, 136, 158, 222, 10, 192, 41, 227},
{174, 229, 7, 70, 206, 29, 89, 189, 213, 188, 33, 212, 151, 193, 254, 218, 239, 38, 5, 110, 143, 97, 37, 81, 142, 18, 93, 184, 110, 93, 251, 91},
{52, 86, 100, 126, 146, 223, 48, 62, 75, 108, 70, 219, 245, 33, 187, 154, 183, 167, 3, 107, 238, 39, 158, 207, 110, 84, 216, 51, 15, 116, 120, 71},
{205, 222, 123, 163, 14, 210, 148, 124, 206, 14, 57, 19, 53, 123, 136, 153, 175, 15, 42, 88, 151, 235, 192, 90, 170, 4, 175, 131, 108, 231, 249, 143},
{148, 139, 48, 211, 158, 147, 117, 33, 102, 77, 237, 218, 77, 54, 170, 68, 39, 24, 6, 237, 106, 137, 131, 98, 25, 203, 36, 104, 92, 38, 238, 241},
{165, 147, 185, 5, 22, 252, 130, 247, 32, 76, 241, 81, 118, 178, 107, 64, 171, 15, 223, 129, 12, 34, 141, 142, 121, 218, 185, 163, 68, 128, 225, 124},
{23, 231, 58, 82, 90, 211, 40, 239, 63, 155, 129, 60, 128, 142, 31, 64, 164, 157, 221, 125, 225, 114, 37, 76, 217, 172, 3, 27, 146, 193, 82, 144},
{88, 207, 100, 97, 177, 177, 65, 193, 199, 91, 12, 22, 17, 189, 51, 16, 199, 144, 46, 188, 87, 110, 210, 240, 211, 202, 253, 98, 143, 190, 114, 1},
{19, 215, 123, 95, 188, 172, 128, 108, 38, 206, 18, 69, 137, 19, 35, 187, 196, 29, 158, 95, 107, 67, 213, 229, 121, 102, 1, 140, 3, 8, 176, 137},
{254, 80, 166, 73, 150, 111, 173, 219, 30, 147, 134, 90, 126, 134, 161, 248, 199, 149, 48, 98, 165, 13, 150, 197, 183, 129, 198, 253, 8, 124, 37, 152},
{192, 42, 26, 56, 12, 149, 104, 49, 152, 50, 118, 99, 251, 83, 191, 154, 145, 109, 86, 254, 190, 138, 28, 230, 102, 101, 198, 8, 70, 104, 191, 253},
{113, 205, 59, 6, 8, 242, 213, 43, 224, 222, 197, 129, 5, 28, 200, 123, 236, 104, 226, 167, 146, 6, 233, 104, 223, 138, 10, 55, 146, 240, 231, 109},
{41, 164, 95, 124, 213, 29, 32, 127, 210, 194, 190, 165, 202, 223, 58, 3, 138, 33, 84, 114, 225, 165, 197, 72, 206, 32, 180, 154, 57, 8, 204, 102},
{132, 124, 62, 144, 115, 15, 9, 136, 217, 163, 11, 119, 222, 6, 194, 64, 125, 170, 127, 248, 166, 74, 7, 152, 84, 50, 72, 24, 24, 123, 86, 214},
{134, 57, 102, 153, 222, 197, 231, 129, 183, 241, 40, 128, 43, 111, 140, 103, 38, 43, 154, 52, 249, 56, 182, 33, 235, 152, 83, 3, 178, 91, 75, 9},
{139, 5, 68, 152, 226, 43, 97, 191, 13, 246, 202, 19, 147, 57, 117, 48, 93, 98, 85, 68, 21, 77, 50, 36, 148, 159, 69, 141, 77, 121, 37, 59},
{218, 35, 129, 104, 183, 103, 180, 64, 135, 243, 110, 82, 44, 229, 61, 124, 225, 211, 61, 172, 216, 110, 173, 55, 22, 43, 189, 188, 227, 32, 38, 163},
{26, 166, 237, 51, 2, 49, 255, 9, 59, 85, 142, 19, 204, 119, 216, 15, 196, 197, 79, 10, 236, 140, 159, 216, 166, 123, 78, 138, 105, 238, 188, 120},
{91, 94, 229, 234, 63, 179, 33, 38, 122, 164, 161, 122, 132, 60, 152, 233, 156, 189, 47, 52, 17, 194, 93, 130, 145, 157, 169, 53, 34, 202, 4, 6},
{106, 94, 193, 127, 30, 113, 21, 207, 78, 76, 15, 10, 31, 136, 95, 143, 43, 122, 153, 20, 252, 105, 127, 239, 147, 8, 29, 146, 110, 23, 238, 36},
{22, 92, 183, 30, 142, 237, 219, 104, 197, 87, 160, 227, 70, 87, 224, 149, 103, 38, 159, 198, 144, 22, 65, 13, 1, 94, 91, 66, 183, 101, 242, 51},
{66, 178, 17, 94, 151, 227, 231, 143, 59, 115, 189, 74, 80, 32, 215, 221, 170, 119, 9, 201, 172, 75, 71, 225, 3, 127, 106, 13, 3, 150, 74, 255},
{87, 76, 214, 123, 201, 83, 193, 254, 141, 111, 22, 216, 15, 179, 154, 30, 30, 250, 228, 26, 22, 60, 67, 93, 215, 152, 155, 121, 85, 166, 5, 115},
{246, 147, 7, 89, 171, 183, 133, 26, 210, 65, 50, 75, 127, 233, 103, 26, 2, 138, 114, 163, 147, 164, 140, 162, 174, 239, 28, 220, 93, 46, 46, 36},
{22, 192, 122, 216, 168, 88, 29, 248, 16, 203, 173, 222, 7, 55, 129, 173, 242, 15, 111, 45, 39, 121, 140, 254, 76, 99, 188, 67, 249, 86, 203, 243},
{131, 18, 135, 57, 186, 240, 43, 197, 42, 40, 229, 131, 81, 252, 75, 102, 247, 115, 212, 10, 127, 71, 22, 239, 234, 248, 154, 217, 173, 54, 141, 178},
{36, 104, 231, 153, 223, 236, 110, 81, 143, 97, 248, 53, 135, 40, 74, 153, 203, 40, 1, 209, 108, 98, 114, 3, 143, 173, 122, 159, 51, 191, 68, 35},
{111, 152, 170, 153, 65, 127, 209, 208, 212, 169, 111, 246, 131, 193, 189, 31, 103, 250, 231, 20, 74, 234, 76, 133, 117, 110, 181, 111, 128, 138, 112, 66},
{146, 12, 235, 186, 103, 104, 193, 4, 124, 188, 140, 74, 193, 7, 180, 13, 137, 74, 65, 20, 68, 11, 96, 99, 119, 68, 85, 70, 200, 201, 49, 183},
{123, 240, 167, 34, 210, 88, 3, 34, 18, 26, 28, 44, 151, 178, 109, 244, 3, 195, 14, 236, 222, 29, 83, 158, 148, 107, 6, 248, 84, 123, 141, 175},
{206, 13, 29, 60, 189, 200, 145, 127, 137, 172, 44, 42, 120, 212, 73, 113, 213, 246, 23, 79, 33, 122, 139, 95, 45, 214, 19, 71, 155, 51, 175, 147},
{109, 154, 79, 11, 165, 113, 9, 15, 99, 246, 224, 96, 187, 67, 214, 195, 151, 146, 87, 229, 1, 146, 10, 7, 70, 252, 199, 225, 112, 35, 146, 236},
{79, 247, 176, 255, 183, 139, 55, 141, 239, 188, 172, 186, 156, 126, 83, 242, 160, 149, 243, 148, 175, 240, 53, 30, 207, 128, 116, 4, 68, 217, 66, 176},
{2, 167, 119, 216, 190, 219, 119, 23, 20, 182, 254, 238, 157, 225, 233, 140, 234, 214, 251, 20, 65, 154, 174, 78, 113, 255, 137, 147, 44, 69, 183, 7},
{121, 136, 140, 214, 241, 237, 76, 180, 152, 43, 84, 28, 20, 147, 28, 118, 154, 214, 252, 177, 11, 45, 156, 43, 214, 93, 180, 195, 169, 158, 111, 108},
{58, 35, 174, 240, 216, 249, 14, 203, 170, 179, 2, 125, 200, 204, 43, 95, 83, 141, 228, 29, 32, 40, 85, 10, 4, 156, 168, 85, 172, 180, 172, 21},
{114, 171, 242, 238, 47, 124, 59, 125, 65, 23, 39, 150, 161, 226, 5, 209, 61, 231, 91, 15, 64, 57, 58, 233, 229, 192, 112, 67, 243, 149, 98, 151},
{33, 32, 3, 8, 36, 151, 121, 17, 218, 26, 98, 82, 65, 146, 162, 149, 64, 53, 126, 112, 58, 163, 159, 106, 238, 218, 218, 91, 237, 109, 12, 234},
{37, 190, 149, 41, 64, 68, 119, 19, 153, 51, 235, 147, 203, 136, 225, 145, 52, 164, 112, 134, 242, 179, 185, 57, 179, 177, 210, 34, 165, 113, 40, 14},
{242, 44, 232, 202, 123, 230, 119, 236, 16, 231, 234, 50, 122, 215, 111, 194, 189, 76, 240, 228, 184, 42, 191, 174, 20, 235, 39, 70, 86, 220, 37, 131},
{64, 190, 225, 105, 2, 122, 16, 3, 38, 255, 79, 66, 166, 97, 192, 141, 229, 219, 13, 65, 91, 86, 37, 100, 207, 90, 214, 150, 47, 118, 157, 109},
{41, 149, 44, 166, 186, 23, 168, 186, 250, 4, 159, 47, 9, 124, 71, 11, 124, 40, 231, 157, 7, 108, 149, 132, 194, 48, 100, 70, 152, 181, 74, 28},
{249, 59, 57, 146, 2, 235, 113, 131, 188, 6, 171, 48, 224, 49, 175, 1, 83, 140, 128, 210, 225, 170, 116, 187, 222, 114, 1, 81, 174, 106, 29, 1},
{19, 118, 143, 2, 79, 31, 218, 92, 100, 181, 79, 226, 175, 226, 175, 39, 213, 137, 130, 241, 5, 245, 17, 67, 50, 107, 185, 112, 48, 41, 100, 230},
{241, 134, 224, 140, 191, 179, 174, 113, 4, 225, 15, 245, 177, 126, 87, 178, 31, 224, 132, 12, 254, 124, 136, 206, 184, 66, 126, 55, 56, 198, 36, 38},
{48, 196, 26, 73, 218, 118, 123, 137, 168, 15, 159, 113, 154, 253, 55, 144, 239, 187, 25, 57, 59, 60, 63, 148, 47, 2, 154, 195, 208, 32, 63, 18},
{11, 43, 62, 251, 191, 45, 35, 203, 140, 42, 121, 233, 87, 190, 201, 82, 228, 103, 71, 184, 123, 78, 40, 6, 227, 199, 165, 59, 95, 91, 220, 223},
{13, 53, 76, 103, 206, 252, 97, 243, 120, 229, 154, 201, 166, 244, 46, 208, 14, 246, 41, 210, 152, 81, 184, 156, 192, 91, 123, 48, 223, 215, 21, 243},
{131, 9, 114, 15, 5, 150, 143, 185, 33, 64, 203, 180, 70, 93, 136, 201, 138, 143, 45, 76, 128, 248, 62, 219, 136, 116, 162, 30, 222, 16, 12, 108},
{58, 217, 47, 14, 1, 13, 117, 8, 167, 10, 105, 226, 96, 158, 229, 203, 236, 157, 189, 204, 221, 163, 128, 168, 244, 194, 129, 67, 113, 195, 34, 118},
{169, 119, 204, 119, 80, 22, 46, 55, 120, 70, 39, 68, 156, 140, 150, 247, 116, 237, 35, 82, 233, 43, 126, 138, 204, 151, 134, 110, 159, 171, 125, 51},
{66, 13, 58, 37, 254, 61, 28, 122, 100, 206, 172, 205, 247, 250, 12, 171, 200, 100, 194, 117, 56, 50, 122, 222, 132, 178, 163, 208, 47, 190, 132, 112},
{195, 10, 135, 248, 143, 167, 184, 176, 98, 179, 72, 42, 214, 23, 145, 9, 214, 47, 254, 22, 152, 182, 82, 194, 171, 126, 118, 119, 87, 192, 36, 181},
{93, 162, 212, 56, 55, 138, 174, 1, 117, 22, 129, 122, 212, 161, 92, 220, 178, 53, 119, 177, 111, 233, 133, 194, 58, 192, 183, 57, 167, 247, 152, 81},
{138, 170, 159, 30, 237, 244, 80, 230, 79, 150, 12, 155, 244, 118, 126, 1, 234, 205, 124, 84, 116, 79, 204, 164, 206, 86, 151, 148, 99, 226, 190, 68},
{248, 236, 70, 21, 20, 138, 236, 107, 34, 17, 24, 130, 201, 124, 96, 217, 85, 33, 82, 180, 204, 77, 120, 81, 71, 102, 237, 95, 104, 31, 125, 89},
{18, 3, 24, 73, 102, 63, 197, 209, 78, 137, 121, 112, 128, 123, 39, 9, 1, 180, 24, 222, 135, 76, 217, 252, 97, 234, 39, 97, 42, 97, 38, 42},
{228, 45, 188, 152, 234, 51, 166, 35, 216, 41, 188, 76, 213, 212, 244, 206, 205, 116, 5, 211, 100, 181, 104, 188, 63, 244, 47, 236, 48, 88, 208, 80},
{153, 156, 164, 77, 144, 52, 216, 195, 138, 50, 122, 239, 93, 117, 149, 33, 44, 104, 51, 87, 193, 80, 43, 126, 57, 230, 104, 125, 215, 242, 31, 247},
{207, 155, 49, 11, 124, 188, 131, 180, 170, 150, 37, 109, 38, 174, 75, 104, 12, 226, 139, 143, 126, 241, 233, 148, 116, 99, 20, 212, 10, 62, 17, 173},
{232, 186, 3, 220, 51, 92, 23, 165, 204, 6, 50, 129, 26, 97, 116, 90, 252, 80, 42, 40, 241, 242, 12, 139, 40, 65, 144, 183, 117, 126, 246, 228},
{215, 126, 89, 118, 198, 245, 143, 230, 46, 91, 46, 26, 241, 207, 245, 100, 215, 96, 65, 70, 148, 160, 228, 189, 127, 47, 223, 252, 61, 144, 111, 95},
{120, 41, 21, 204, 241, 163, 28, 92, 171, 179, 152, 237, 125, 79, 247, 139, 126, 208, 125, 246, 189, 108, 137, 210, 156, 75, 238, 104, 210, 1, 141, 24},
{181, 108, 111, 71, 59, 212, 1, 131, 225, 115, 37, 14, 100, 77, 222, 171, 164, 193, 64, 145, 241, 64, 162, 123, 150, 194, 113, 2, 25, 6, 145, 13},
{199, 48, 251, 125, 111, 186, 180, 237, 180, 132, 113, 39, 91, 126, 21, 120, 230, 175, 135, 71, 203, 21, 156, 236, 208, 12, 20, 118, 213, 244, 64, 42},
{228, 248, 143, 123, 222, 58, 35, 82, 228, 211, 177, 68, 130, 15, 241, 252, 188, 147, 30, 76, 253, 249, 49, 249, 47, 69, 201, 223, 39, 167, 69, 54},
{29, 201, 235, 177, 124, 218, 197, 238, 93, 127, 73, 43, 46, 238, 83, 94, 96, 57, 138, 224, 138, 98, 197, 122, 96, 10, 177, 55, 102, 167, 190, 120},
{91, 89, 138, 236, 189, 205, 202, 28, 157, 194, 139, 189, 188, 222, 1, 98, 205, 25, 211, 241, 251, 164, 179, 216, 51, 91, 216, 202, 159, 197, 77, 4},
{76, 93, 179, 102, 191, 201, 9, 126, 167, 185, 251, 178, 251, 180, 156, 27, 21, 130, 33, 10, 138, 171, 114, 111, 198, 221, 80, 1, 83, 185, 253, 134},
{31, 137, 206, 229, 32, 215, 202, 228, 232, 101, 97, 35, 255, 234, 127, 236, 159, 230, 245, 56, 25, 32, 201, 66, 153, 211, 32, 73, 144, 210, 206, 133},
{42, 86, 219, 213, 217, 111, 135, 80, 70, 49, 102, 98, 210, 232, 158, 138, 9, 31, 131, 127, 79, 143, 146, 160, 50, 78, 110, 170, 123, 133, 183, 166},
{69, 223, 198, 190, 49, 54, 2, 163, 119, 185, 60, 107, 37, 131, 9, 62, 145, 184, 181, 28, 147, 95, 19, 12, 166, 4, 235, 241, 135, 215, 47, 217},
{103, 126, 39, 5, 127, 60, 220, 60, 120, 40, 162, 39, 65, 138, 112, 7, 160, 101, 210, 27, 244, 193, 20, 21, 219, 135, 56, 69, 78, 58, 189, 32},
{90, 87, 125, 20, 167, 248, 82, 21, 141, 69, 253, 119, 45, 1, 160, 160, 152, 226, 184, 84, 228, 78, 63, 186, 229, 248, 223, 190, 249, 99, 231, 171},
{130, 42, 80, 10, 216, 201, 245, 154, 5, 23, 74, 242, 101, 102, 184, 166, 246, 34, 14, 32, 226, 16, 14, 239, 23, 73, 139, 71, 68, 184, 143, 50},
{81, 169, 211, 130, 94, 168, 242, 140, 46, 186, 180, 233, 222, 1, 120, 13, 77, 60, 3, 41, 157, 45, 250, 153, 104, 220, 182, 172, 103, 226, 153, 121},
{72, 154, 94, 239, 83, 242, 137, 6, 24, 184, 7, 9, 225, 44, 112, 193, 74, 238, 216, 9, 229, 167, 71, 208, 89, 230, 197, 188, 101, 67, 6, 216},
{116, 252, 214, 166, 243, 67, 41, 154, 58, 78, 234, 85, 188, 76, 65, 246, 139, 100, 138, 7, 54, 163, 87, 118, 142, 205, 17, 26, 98, 95, 39, 242},
{144, 255, 15, 174, 25, 182, 1, 220, 175, 11, 41, 141, 69, 69, 174, 46, 120, 208, 177, 158, 130, 66, 119, 3, 235, 143, 255, 5, 149, 42, 138, 165},
{112, 233, 174, 39, 48, 209, 136, 82, 207, 75, 221, 255, 118, 18, 27, 139, 84, 186, 104, 189, 22, 174, 14, 176, 131, 31, 106, 243, 139, 173, 146, 244},
{250, 254, 133, 76, 108, 59, 53, 147, 15, 200, 135, 17, 138, 131, 147, 99, 199, 233, 75, 71, 240, 26, 199, 232, 60, 27, 173, 69, 39, 246, 92, 48},
{119, 210, 114, 33, 191, 38, 98, 22, 244, 162, 249, 182, 30, 234, 188, 43, 61, 164, 212, 142, 73, 23, 155, 62, 96, 128, 111, 104, 167, 146, 203, 65},
{167, 152, 96, 47, 165, 177, 203, 192, 142, 135, 92, 7, 61, 156, 32, 137, 220, 99, 13, 180, 186, 52, 77, 237, 74, 147, 251, 15, 108, 122, 59, 28},
{249, 181, 52, 222, 139, 244, 215, 224, 198, 114, 40, 243, 200, 5, 79, 102, 209, 44, 203, 56, 200, 23, 44, 99, 183, 250, 162, 206, 231, 158, 210, 112},
{195, 177, 63, 246, 116, 210, 113, 123, 248, 17, 244, 174, 232, 40, 110, 74, 27, 54, 182, 31, 213, 70, 119, 148, 22, 77, 62, 118, 73, 8, 4, 227},
{174, 223, 121, 235, 197, 225, 150, 67, 127, 80, 219, 62, 36, 51, 65, 225, 209, 187, 13, 144, 188, 232, 86, 67, 248, 61, 152, 24, 198, 30, 51, 118},
{169, 227, 202, 33, 181, 210, 194, 212, 51, 158, 125, 246, 64, 200, 59, 83, 94, 208, 5, 226, 181, 74, 53, 92, 39, 155, 121, 119, 196, 28, 160, 34},
{124, 154, 149, 143, 36, 8, 222, 81, 182, 28, 217, 58, 223, 4, 195, 230, 121, 181, 17, 97, 174, 39, 223, 245, 163, 115, 72, 29, 9, 250, 221, 93},
{94, 129, 132, 118, 175, 123, 131, 87, 207, 57, 77, 136, 126, 101, 29, 176, 73, 215, 180, 68, 41, 126, 101, 135, 219, 224, 57, 29, 241, 38, 251, 65},
{167, 177, 51, 217, 242, 161, 150, 33, 207, 188, 199, 179, 3, 252, 175, 40, 71, 23, 126, 212, 112, 84, 36, 19, 243, 40, 155, 89, 25, 44, 143, 44},
{142, 157, 145, 41, 142, 233, 158, 158, 64, 158, 34, 89, 115, 91, 16, 81, 46, 212, 130, 142, 166, 58, 205, 243, 193, 255, 109, 107, 83, 94, 185, 217},
{103, 181, 101, 82, 232, 131, 3, 160, 69, 31, 133, 57, 115, 220, 168, 30, 207, 218, 190, 44, 102, 244, 113, 203, 36, 224, 195, 195, 212, 238, 52, 182},
{104, 138, 170, 151, 231, 202, 217, 205, 81, 42, 246, 108, 123, 2, 40, 96, 196, 95, 144, 98, 49, 43, 23, 184, 181, 141, 105, 31, 176, 224, 164, 81},
{138, 159, 183, 96, 66, 36, 16, 145, 131, 178, 48, 236, 226, 217, 221, 117, 86, 187, 22, 179, 167, 17, 14, 54, 180, 217, 218, 74, 69, 245, 169, 120},
{91, 206, 220, 176, 108, 243, 52, 201, 226, 28, 70, 196, 123, 18, 54, 236, 230, 47, 81, 109, 168, 137, 192, 19, 127, 143, 11, 161, 226, 230, 31, 19},
{24, 207, 128, 6, 155, 134, 151, 169, 43, 105, 35, 121, 125, 93, 184, 219, 76, 180, 221, 129, 248, 201, 38, 206, 237, 34, 227, 219, 92, 238, 20, 4},
{76, 30, 37, 108, 85, 239, 66, 35, 18, 15, 80, 26, 63, 117, 31, 162, 172, 3, 140, 4, 250, 168, 31, 250, 208, 3, 41, 58, 66, 122, 214, 223},
{13, 114, 121, 124, 89, 22, 163, 146, 144, 123, 191, 224, 85, 156, 229, 6, 254, 190, 77, 25, 36, 208, 94, 171, 60, 104, 191, 188, 222, 202, 52, 249},
{61, 6, 137, 137, 31, 211, 146, 84, 248, 242, 181, 113, 192, 186, 69, 59, 7, 72, 9, 101, 14, 204, 101, 246, 140, 62, 12, 151, 191, 78, 125, 45},
{157, 136, 146, 168, 3, 25, 221, 183, 210, 160, 37, 98, 46, 154, 200, 51, 233, 78, 211, 136, 192, 80, 238, 133, 173, 53, 176, 141, 252, 127, 213, 208},
{236, 37, 13, 175, 18, 251, 87, 187, 224, 204, 128, 5, 91, 147, 115, 122, 151, 89, 90, 163, 65, 38, 17, 122, 231, 248, 212, 192, 124, 138, 107, 170},
{145, 19, 150, 65, 190, 97, 199, 178, 76, 115, 138, 198, 136, 18, 180, 253, 248, 247, 187, 179, 194, 161, 221, 246, 94, 254, 64, 61, 91, 186, 104, 69},
{235, 120, 75, 39, 150, 196, 72, 209, 145, 27, 180, 77, 11, 2, 154, 155, 125, 233, 102, 2, 252, 239, 45, 119, 156, 67, 142, 249, 160, 160, 43, 116},
{143, 165, 24, 101, 222, 187, 133, 80, 114, 98, 164, 11, 16, 227, 43, 133, 145, 213, 75, 107, 148, 34, 89, 73, 28, 136, 140, 131, 231, 105, 2, 209},
{255, 184, 148, 30, 2, 59, 196, 206, 224, 101, 11, 205, 173, 175, 148, 17, 245, 251, 207, 74, 117, 102, 216, 250, 162, 252, 162, 141, 19, 22, 115, 134},
{31, 58, 43, 194, 88, 106, 56, 41, 88, 34, 189, 211, 128, 188, 100, 228, 149, 6, 140, 214, 89, 223, 4, 232, 12, 183, 1, 187, 28, 146, 97, 11},
{173, 159, 50, 163, 30, 151, 172, 58, 118, 11, 139, 20, 227, 150, 135, 213, 107, 120, 100, 176, 68, 197, 190, 248, 82, 15, 225, 61, 55, 196, 240, 250},
{8, 42, 165, 143, 186, 179, 64, 44, 100, 15, 30, 158, 136, 10, 240, 220, 181, 174, 221, 223, 195, 144, 160, 79, 89, 146, 43, 90, 157, 51, 97, 249},
{61, 3, 209, 85, 236, 48, 55, 183, 70, 6, 193, 208, 190, 103, 211, 46, 221, 3, 25, 245, 200, 43, 37, 8, 104, 91, 246, 3, 89, 13, 132, 120},
{91, 121, 64, 214, 89, 93, 32, 238, 196, 217, 242, 53, 71, 78, 136, 226, 189, 164, 233, 98, 238, 230, 250, 56, 65, 83, 137, 141, 171, 250, 231, 62},
{133, 122, 163, 187, 119, 181, 55, 152, 138, 23, 49, 26, 211, 59, 150, 19, 144, 166, 205, 184, 82, 209, 107, 20, 157, 165, 177, 216, 27, 103, 147, 81},
{138, 114, 71, 105, 110, 180, 111, 127, 214, 105, 13, 43, 148, 113, 228, 203, 37, 239, 239, 238, 125, 114, 244, 74, 24, 241, 242, 146, 130, 94, 46, 79},
{85, 108, 150, 69, 191, 198, 106, 86, 228, 219, 78, 42, 73, 10, 92, 242, 16, 3, 18, 27, 228, 216, 36, 149, 19, 179, 28, 6, 226, 38, 163, 82},
{191, 46, 144, 17, 234, 91, 79, 85, 44, 28, 26, 143, 24, 237, 106, 132, 165, 28, 88, 162, 186, 248, 45, 92, 31, 189, 164, 172, 255, 51, 125, 111},
{15, 105, 201, 161, 101, 197, 235, 191, 127, 28, 238, 232, 231, 198, 234, 172, 192, 193, 60, 42, 87, 165, 80, 226, 245, 151, 8, 214, 96, 118, 19, 23},
{84, 157, 205, 255, 217, 251, 101, 194, 230, 208, 26, 232, 23, 201, 46, 29, 123, 221, 11, 53, 196, 102, 220, 130, 2, 70, 240, 1, 178, 74, 188, 195},
{244, 120, 86, 42, 110, 203, 209, 158, 119, 115, 207, 5, 104, 140, 138, 113, 25, 153, 59, 171, 105, 67, 136, 70, 30, 10, 203, 80, 13, 200, 172, 216},
{116, 64, 52, 174, 54, 126, 16, 194, 162, 33, 33, 157, 176, 197, 225, 12, 59, 55, 253, 228, 148, 47, 179, 185, 24, 138, 253, 20, 142, 55, 172, 88}};
auto rs = std::make_unique<ReedSolomon>(nroots, minpoly, prim, fcr, pad, shortening, genpoly_coeff, genmatrix);
std::vector<uint8_t> encoded_output = rs->encode_with_generator_matrix(input);
EXPECT_TRUE(encoded_output == expected_output);
}
TEST(ReedSolomonE6BTest, DecodeNoErrors)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
auto rs = std::make_unique<ReedSolomon>();
int result = rs->decode(encoded_input);
EXPECT_TRUE(result == 0);
std::vector<uint8_t> decoded(encoded_input.begin(), encoded_input.begin() + 32);
EXPECT_TRUE(expected_output == decoded);
}
TEST(ReedSolomonE6BTest, Decode1Error)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce 1 error:
encoded_input[23] = 0;
auto rs = std::make_unique<ReedSolomon>();
int result = rs->decode(encoded_input);
EXPECT_TRUE(result == 1);
std::vector<uint8_t> decoded(encoded_input.begin(), encoded_input.begin() + 32);
EXPECT_TRUE(expected_output == decoded);
}
TEST(ReedSolomonE6BTest, Decode16Errors)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce 16 errors:
encoded_input[3] = 0;
encoded_input[23] = 0;
encoded_input[55] = 0;
encoded_input[72] = 0;
encoded_input[85] = 0;
encoded_input[105] = 0;
encoded_input[123] = 0;
encoded_input[147] = 0;
encoded_input[174] = 0;
encoded_input[188] = 0;
encoded_input[195] = 0;
encoded_input[203] = 0;
encoded_input[208] = 0;
encoded_input[222] = 0;
encoded_input[233] = 0;
encoded_input[244] = 0;
auto rs = std::make_unique<ReedSolomon>();
int result = rs->decode(encoded_input);
EXPECT_TRUE(result == 16);
std::vector<uint8_t> decoded(encoded_input.begin(), encoded_input.begin() + 32);
EXPECT_TRUE(expected_output == decoded);
}
TEST(ReedSolomonE6BTest, Decode111Errors)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce t = (n-k)/2 = 111 errors:
for (int i = 0; i < 222; i += 2)
{
encoded_input[i] = 0;
}
auto rs = std::make_unique<ReedSolomon>();
int result = rs->decode(encoded_input);
EXPECT_TRUE(result == 111);
std::vector<uint8_t> decoded(encoded_input.begin(), encoded_input.begin() + 32);
EXPECT_TRUE(expected_output == decoded);
}
TEST(ReedSolomonE6BTest, Decode111ErrorsCustomConstructor)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce t = (n-k)/2 = 111 errors:
for (int i = 0; i < 222; i += 2)
{
encoded_input[i] = 0;
}
int nroots = 223;
int minpoly = 29;
int prim = 1;
int fcr = 1;
auto rs = std::make_unique<ReedSolomon>(nroots, minpoly, prim, fcr);
int result = rs->decode(encoded_input);
EXPECT_TRUE(result == 111);
std::vector<uint8_t> decoded(encoded_input.begin(), encoded_input.begin() + 32);
EXPECT_TRUE(expected_output == decoded);
}
TEST(ReedSolomonE6BTest, Decode112Errors)
{
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce 112 errors (this should make the decoder fail):
for (int i = 0; i < 224; i += 2)
{
encoded_input[i] = 0;
}
auto rs = std::make_unique<ReedSolomon>();
int result = rs->decode(encoded_input);
EXPECT_TRUE(result == -1);
}
TEST(ReedSolomonE6BTest, Decode113ErrorsWithErasure)
{
const std::vector<uint8_t> expected_output = {71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179};
std::vector<uint8_t> encoded_input = {
71, 12, 25, 210, 178, 81, 243, 9, 112, 98, 196, 203, 48, 125, 114, 165, 181, 193, 71, 174, 168, 42, 31, 128, 245, 87, 150, 58, 192, 66, 130, 179, 133, 210, 122, 224, 75, 138, 20, 205, 14, 245, 209, 187, 246, 228, 12, 39, 244, 238, 223, 217, 84, 233, 137, 168, 153, 8, 94, 26, 99, 169, 149, 203, 115, 69, 211, 43, 70, 96, 70, 38, 160, 1, 232, 153, 223, 165, 93, 205, 101, 170, 60, 188, 198, 82, 168, 79, 95, 23, 118, 215, 187, 136, 24, 99, 252, 3, 144, 166, 117, 45, 168, 239, 77, 42, 246, 33, 122, 97, 242, 236, 13, 217, 96, 186, 71, 250, 242, 177, 125, 87, 27, 13, 118, 181, 178, 12, 27, 66, 31, 74, 127, 46, 112, 127, 116, 122, 190, 71, 240, 95, 78, 194, 113, 80, 46, 126, 74, 136, 118, 133, 105, 176, 47, 230, 162, 195, 93, 157, 72, 119, 13, 232, 151, 200, 191, 143, 75, 161, 111, 29, 158, 16, 181, 165, 92, 39, 17, 218, 228, 58, 176, 233, 55, 211, 195, 73, 37, 137, 232, 241, 150, 236, 152, 153, 53, 74, 81, 91, 160, 244, 21, 95, 176, 179, 141, 39, 61, 136, 16, 58, 160, 51, 210, 31, 134, 63, 203, 96, 219, 44, 231, 61, 220, 0, 241, 220, 207, 17, 52, 150, 117, 54, 222, 128, 101, 213, 164, 234, 74, 224, 57, 246, 70, 27, 202, 229, 4, 243, 128, 211, 158, 199, 4};
// Introduce 113 errors:
for (int i = 0; i < 226; i += 2)
{
encoded_input[i] = 0;
}
std::vector<int> erasure_positions{2, 4, 16, 18, 22, 54};
auto rs = std::make_unique<ReedSolomon>();
int result = rs->decode(encoded_input, erasure_positions);
EXPECT_TRUE(result == 113);
std::vector<uint8_t> decoded(encoded_input.begin(), encoded_input.begin() + 32);
EXPECT_TRUE(expected_output == decoded);
}