kopia lustrzana https://github.com/mobilinkd/m17-cxx-demod
Don't count erasures (punctures) in the Viterbi cost metric. Minor cleanup in the LLR code, along with more unit tests.
rodzic
fe1ac10581
commit
05a1e3bbb3
|
@ -30,19 +30,47 @@ constexpr std::bitset<sizeof...(Is)> make_bitset(std::index_sequence<Is...>, Tup
|
|||
return result;
|
||||
}
|
||||
|
||||
template<typename FloatType, size_t LLR>
|
||||
constexpr std::array<std::tuple<FloatType, std::tuple<int8_t, int8_t>>, (((1 << (LLR - 1)) - 1) * 6 ) + 1> make_llr_map()
|
||||
/**
|
||||
* This is the max value for the LLR based on size N.
|
||||
*/
|
||||
template <size_t N>
|
||||
constexpr size_t llr_limit()
|
||||
{
|
||||
constexpr size_t size = (((1 << (LLR - 1)) - 1) * 6 ) + 1;
|
||||
return (1 << (N - 1)) - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* There are (2^(N-1)-1) elements (E) per segment (e.g. N=4, E=7; N=3, E=3).
|
||||
* These contain the LLR values 1..E. There are 6 segments in the LLR map:
|
||||
* 1. (-Inf,-2]
|
||||
* 2. (-2, -1]
|
||||
* 3. (-1, 0]
|
||||
* 4. (0, 1]
|
||||
* 5. (1, 2]
|
||||
* 6. (2, Inf)
|
||||
*
|
||||
* Note the slight asymmetry. This is OK as we are dealing with floats and
|
||||
* it only matters to an epsilon of the float type.
|
||||
*/
|
||||
template <size_t N>
|
||||
constexpr size_t llr_size()
|
||||
{
|
||||
return llr_limit<N>() * 6 + 1;
|
||||
}
|
||||
|
||||
template<typename FloatType, size_t LLR>
|
||||
constexpr std::array<std::tuple<FloatType, std::tuple<int8_t, int8_t>>, llr_size<LLR>()> make_llr_map()
|
||||
{
|
||||
constexpr size_t size = llr_size<LLR>();
|
||||
std::array<std::tuple<FloatType, std::tuple<int8_t, int8_t>>, size> result;
|
||||
|
||||
constexpr int8_t limit = (1 << (LLR - 1)) - 1;
|
||||
constexpr int8_t limit = llr_limit<LLR>();
|
||||
constexpr FloatType inc = 1.0 / FloatType(limit);
|
||||
int8_t i = limit;
|
||||
int8_t j = limit;
|
||||
|
||||
// Output must be ordered by k, ascending.
|
||||
FloatType k = -3.0;
|
||||
FloatType k = -3.0 + inc;
|
||||
for (size_t index = 0; index != size; ++index)
|
||||
{
|
||||
auto& a = result[index];
|
||||
|
@ -50,19 +78,22 @@ constexpr std::array<std::tuple<FloatType, std::tuple<int8_t, int8_t>>, (((1 <<
|
|||
std::get<0>(std::get<1>(a)) = i;
|
||||
std::get<1>(std::get<1>(a)) = j;
|
||||
|
||||
if (k + 1.0 < inc / -2.0)
|
||||
if (k + 1.0 < 0)
|
||||
{
|
||||
j--;
|
||||
if (j == 0) j = -1;
|
||||
if (j < -limit) j = -limit;
|
||||
}
|
||||
else if (k - 1.0 < inc / -2.0)
|
||||
else if (k - 1.0 < 0)
|
||||
{
|
||||
i--;
|
||||
if (i == 0) i = -1;
|
||||
if (i < -limit) i = -limit;
|
||||
}
|
||||
else
|
||||
{
|
||||
j++;
|
||||
if (j == 0) j = 1;
|
||||
if (j > limit) j = limit;
|
||||
}
|
||||
k += inc;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "Util.h"
|
||||
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
namespace mobilinkd
|
||||
{
|
||||
|
@ -104,7 +105,7 @@ struct Viterbi
|
|||
prevMetrics[0] = 0; // Starting point.
|
||||
|
||||
std::array<std::bitset<NumStates>, IN / 2> history;
|
||||
// history.fill(0);
|
||||
history.fill(0);
|
||||
|
||||
constexpr size_t BUTTERFLY_SIZE = NumStates / 2;
|
||||
|
||||
|
@ -120,10 +121,18 @@ struct Viterbi
|
|||
|
||||
for (size_t j = 0; j != BUTTERFLY_SIZE; ++j)
|
||||
{
|
||||
int16_t c = std::abs(cost_[j][0] - s0) + std::abs(cost_[j][1] - s1);
|
||||
cost0[j] = c;
|
||||
// cost1[j] = METRIC - c;
|
||||
cost1[j] = std::abs(cost_[j][0] + s0) + std::abs(cost_[j][1] + s1);
|
||||
cost0[j] = 0;
|
||||
cost1[j] = 0;
|
||||
if (s0)
|
||||
{
|
||||
cost0[j] += std::abs(cost_[j][0] - s0);
|
||||
cost1[j] += std::abs(cost_[j][0] + s0);
|
||||
}
|
||||
if (s1)
|
||||
{
|
||||
cost0[j] += std::abs(cost_[j][1] - s1);
|
||||
cost1[j] += std::abs(cost_[j][1] + s1);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t j = 0; j != BUTTERFLY_SIZE; ++j)
|
||||
|
@ -167,7 +176,7 @@ struct Viterbi
|
|||
}
|
||||
}
|
||||
|
||||
size_t ber = min_cost / (METRIC >> 1); // Cost is at least equal to # of erasures.
|
||||
size_t ber = std::round(min_cost / float(detail::llr_limit<LLR_>())); // Cost is at least equal to # of erasures.
|
||||
|
||||
// Do chainback.
|
||||
auto oit = std::rbegin(out);
|
||||
|
|
|
@ -106,4 +106,100 @@ TEST_F(UtilTest, puncture_bytes)
|
|||
EXPECT_EQ(get_bit_index(out, 53), 0);
|
||||
EXPECT_EQ(get_bit_index(out, 54), 1);
|
||||
EXPECT_EQ(get_bit_index(out, 55), 0);
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_size)
|
||||
{
|
||||
auto s = mobilinkd::detail::llr_size<4>();
|
||||
EXPECT_EQ(s, 43) << "size = " << s;
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_not_zero)
|
||||
{
|
||||
for (float i = -4.0; i < 4.0; i += 0.1)
|
||||
{
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(i);
|
||||
EXPECT_NE(int(a), 0) << i << ", a = " << int(a);
|
||||
EXPECT_NE(int(b), 0) << i << ", b = " << int(b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_near_zero)
|
||||
{
|
||||
{
|
||||
float v = 0.0001;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), -1) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -7) << v << ", b = " << int(b);
|
||||
}
|
||||
{
|
||||
float v = -0.0001;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), 1) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -7) << v << ", b = " << int(b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_near_one)
|
||||
{
|
||||
{
|
||||
float v = 1.0001;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), -7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -7) << v << ", b = " << int(b);
|
||||
}
|
||||
{
|
||||
float v = 0.9999;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), -7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -7) << v << ", b = " << int(b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_near_two)
|
||||
{
|
||||
{
|
||||
float v = 2.0001;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), -7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), 1) << v << ", b = " << int(b);
|
||||
}
|
||||
{
|
||||
float v = 1.9999;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), -7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -1) << v << ", b = " << int(b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_near_minus_one)
|
||||
{
|
||||
{
|
||||
float v = -1.0001;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), 7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -7) << v << ", b = " << int(b);
|
||||
}
|
||||
{
|
||||
float v = -0.9999;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), 7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -7) << v << ", b = " << int(b);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(UtilTest, llr_near_minus_two)
|
||||
{
|
||||
{
|
||||
float v = -2.0001;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), 7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), 1) << v << ", b = " << int(b);
|
||||
}
|
||||
{
|
||||
float v = -1.9999;
|
||||
auto [a, b] = mobilinkd::llr<float, 4>(v);
|
||||
EXPECT_EQ(int(a), 7) << v << ", a = " << int(a);
|
||||
EXPECT_EQ(int(b), -1) << v << ", b = " << int(b);
|
||||
}
|
||||
}
|
|
@ -143,7 +143,7 @@ TEST_F(ViterbiTest, decode_ber_1)
|
|||
auto ber = viterbi.decode(encoded,output);
|
||||
for (size_t i = 0; i != expected.size(); ++i) EXPECT_EQ(output[i], expected[i]);
|
||||
|
||||
EXPECT_EQ(ber, 1);
|
||||
EXPECT_EQ(ber, 2);
|
||||
}
|
||||
|
||||
TEST_F(ViterbiTest, decode_ber_llr)
|
||||
|
@ -165,7 +165,7 @@ TEST_F(ViterbiTest, decode_ber_llr)
|
|||
auto ber = viterbi.decode(encoded, output);
|
||||
auto end = std::chrono::high_resolution_clock::now();
|
||||
std::cout << "Duration: " << (end - start).count() << "ns" << std::endl;
|
||||
EXPECT_EQ(ber, 1);
|
||||
EXPECT_EQ(ber, 2);
|
||||
for (size_t i = 0; i != expected.size(); ++i) EXPECT_EQ(output[i], expected[i]);
|
||||
|
||||
}
|
||||
|
@ -223,6 +223,53 @@ TEST_F(ViterbiTest, decode_depuncture_lsf)
|
|||
|
||||
std::cout << "Duration: " << std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() << "ns" << std::endl;
|
||||
std::cout << "Cost: " << ber / 10000 << std::endl;
|
||||
EXPECT_GT(ber, 0);
|
||||
EXPECT_EQ(ber, 0);
|
||||
for (size_t i = 0; i != expected.size(); ++i) EXPECT_EQ(output[i], expected[i]) << "i = " << i;
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ViterbiTest, decode_depuncture_lsf_1_error)
|
||||
{
|
||||
std::array<uint8_t, 240> expected = {1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0};
|
||||
std::array<int8_t, 368> punctured = {1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 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, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0};
|
||||
std::array<int8_t, 488> expected_depunctured = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 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, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
std::array<uint8_t, 244> output;
|
||||
|
||||
for (size_t i = 0; i != punctured.size(); ++i)
|
||||
{
|
||||
punctured[i] = punctured[i] * 2 - 1;
|
||||
}
|
||||
|
||||
mobilinkd::Trellis<4,2> trellis({031,027});
|
||||
mobilinkd::Viterbi<decltype(trellis)> viterbi(trellis);
|
||||
|
||||
auto depunctured = mobilinkd::depunctured<488>(mobilinkd::P1, punctured);
|
||||
depunctured[8] = 1;
|
||||
auto cost = viterbi.decode(depunctured, output);
|
||||
|
||||
EXPECT_EQ(cost, 2);
|
||||
for (size_t i = 0; i != expected.size(); ++i) EXPECT_EQ(output[i], expected[i]) << "i = " << i;
|
||||
}
|
||||
|
||||
TEST_F(ViterbiTest, decode_llr4_1_error)
|
||||
{
|
||||
std::array<uint8_t, 240> expected = {1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0};
|
||||
std::array<int8_t, 368> punctured = {1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 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, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 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, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0};
|
||||
std::array<int8_t, 488> expected_depunctured = {1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 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, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
std::array<uint8_t, 244> output;
|
||||
|
||||
for (size_t i = 0; i != punctured.size(); ++i)
|
||||
{
|
||||
punctured[i] = punctured[i] * 14 - 7;
|
||||
}
|
||||
|
||||
mobilinkd::Trellis<4,2> trellis({031,027});
|
||||
mobilinkd::Viterbi<decltype(trellis), 4> viterbi(trellis);
|
||||
|
||||
auto depunctured = mobilinkd::depunctured<488>(mobilinkd::P1, punctured);
|
||||
depunctured[8] = -1;
|
||||
auto cost = viterbi.decode(depunctured, output);
|
||||
|
||||
EXPECT_EQ(cost, 1);
|
||||
for (size_t i = 0; i != expected.size(); ++i) EXPECT_EQ(output[i], expected[i]) << "i = " << i;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue