Skip to content

Commit

Permalink
Rework unit testing of FEC codes
Browse files Browse the repository at this point in the history
  • Loading branch information
mhostetter committed Aug 7, 2021
1 parent ed8f435 commit e90642a
Show file tree
Hide file tree
Showing 14 changed files with 545 additions and 210 deletions.
2 changes: 2 additions & 0 deletions galois/_code/_bch.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ def bch_valid_codes(n, t_min=1):
galois.bch_valid_codes(31)
galois.bch_valid_codes(31, t_min=3)
"""
if not isinstance(n, (int, np.integer)):
raise TypeError(f"Argument `n` must be an integer, not {type(n)}.")
if not isinstance(t_min, (int, np.integer)):
raise TypeError(f"Argument `t_min` must be an integer, not {type(t_min)}.")
if not t_min >= 1:
Expand Down
4 changes: 2 additions & 2 deletions galois/_code/_linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def generator_to_parity_check_matrix(G):
G @ H.T
"""
if not isinstance(G, (FieldArray)):
raise TypeError(f"Argument `G` must be an np.ndarray or galois.FieldArray, not {type(G)}.")
raise TypeError(f"Argument `G` must be a galois.FieldArray, not {type(G)}.")

field = type(G)
k, n = G.shape
Expand Down Expand Up @@ -80,7 +80,7 @@ def parity_check_to_generator_matrix(H):
G2 @ H.T
"""
if not isinstance(H, (FieldArray)):
raise TypeError(f"Argument `H` must be an np.ndarray or galois.FieldArray, not {type(H)}.")
raise TypeError(f"Argument `H` must be a galois.FieldArray, not {type(H)}.")

field = type(H)
n_k, n = H.shape
Expand Down
214 changes: 49 additions & 165 deletions tests/codes/test_bch.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,178 +9,42 @@
* https://link.springer.com/content/pdf/bbm%3A978-1-4899-2174-1%2F1.pdf
* https://octave.sourceforge.io/communications/function/bchpoly.html
"""
import pytest
import numpy as np

import galois


def test_bch_valid_codes_7():
codes = np.array([
[7, 4, 1],
])
assert np.array_equal(galois.bch_valid_codes(7), codes)


def test_bch_valid_codes_15():
codes = np.array([
[15, 11, 1],
[15, 7, 2],
[15, 5, 3],
])
assert np.array_equal(galois.bch_valid_codes(15), codes)
def test_bch_exceptions():
with pytest.raises(TypeError):
galois.BCH(15.0, 7)
with pytest.raises(TypeError):
galois.BCH(15, 7.0)
with pytest.raises(TypeError):
galois.BCH(15, 7, c=1.0)
with pytest.raises(TypeError):
galois.BCH(15, 7, primitive_poly=19.0)
with pytest.raises(TypeError):
galois.BCH(15, 7, primitive_element=2.0)
with pytest.raises(TypeError):
galois.BCH(15, 7, systematic=1)

with pytest.raises(ValueError):
galois.BCH(15, 12)
with pytest.raises(ValueError):
galois.BCH(14, 7)
# with pytest.raises(ValueError):
# galois.BCH(15, 7, c=0)


def test_str():
bch = galois.BCH(15, 7)
assert str(bch) == "<BCH Code: [15, 7, 5] over GF(2)>"


def test_bch_valid_codes_31():
codes = np.array([
[31, 26, 1],
[31, 21, 2],
[31, 16, 3],
[31, 11, 5],
[31, 6, 7],
])
assert np.array_equal(galois.bch_valid_codes(31), codes)


def test_bch_valid_codes_63():
codes = np.array([
[63, 57, 1],
[63, 51, 2],
[63, 45, 3],
[63, 39, 4],
[63, 36, 5],
[63, 30, 6],
[63, 24, 7],
[63, 18,10],
[63, 16,11],
[63, 10,13],
[63, 7,15],
])
assert np.array_equal(galois.bch_valid_codes(63), codes)


def test_bch_valid_codes_127():
codes = np.array([
[127, 120, 1],
[127, 113, 2],
[127, 106, 3],
[127, 99, 4],
[127, 92, 5],
[127, 85, 6],
[127, 78, 7],
[127, 71, 9],
[127, 64, 10],
[127, 57, 11],
[127, 50, 13],
[127, 43, 14],
[127, 36, 15],
[127, 29, 21],
[127, 22, 23],
[127, 15, 27],
[127, 8, 31],
])
assert np.array_equal(galois.bch_valid_codes(127), codes)


def test_bch_valid_codes_255():
codes = np.array([
[255, 247, 1],
[255, 239, 2],
[255, 231, 3],
[255, 223, 4],
[255, 215, 5],
[255, 207, 6],
[255, 199, 7],
[255, 191, 8],
[255, 187, 9],
[255, 179, 10],
[255, 171, 11],
[255, 163, 12],
[255, 155, 13],
[255, 147, 14],
[255, 139, 15],
[255, 131, 18],
[255, 123, 19],
[255, 115, 21],
[255, 107, 22],
[255, 99, 23],
[255, 91, 25],
[255, 87, 26],
[255, 79, 27],
[255, 71, 29],
[255, 63, 30],
[255, 55, 31],
[255, 47, 42],
[255, 45, 43],
[255, 37, 45],
[255, 29, 47],
[255, 21, 55],
[255, 13, 59],
[255, 9, 63],
])
assert np.array_equal(galois.bch_valid_codes(255), codes)


def test_bch_valid_codes_511():
codes = np.array([
[511, 502, 1],
[511, 493, 2],
[511, 484, 3],
[511, 475, 4],
[511, 466, 5],
[511, 457, 6],
[511, 448, 7],
[511, 439, 8],
[511, 430, 9],
[511, 421, 10],
[511, 412, 11],
[511, 403, 12],
[511, 394, 13],
[511, 385, 14],
[511, 376, 15],
[511, 367, 17],
[511, 358, 18],
[511, 349, 19],
[511, 340, 20],
[511, 331, 21],
[511, 322, 22],
[511, 313, 23],
[511, 304, 25],
[511, 295, 26],
[511, 286, 27],
[511, 277, 28],
[511, 268, 29],
[511, 259, 30],
[511, 250, 31],
[511, 241, 36],
[511, 238, 37],
[511, 229, 38],
[511, 220, 39],
[511, 211, 41],
[511, 202, 42],
[511, 193, 43],
[511, 184, 45],
[511, 175, 46],
[511, 166, 47],
[511, 157, 51],
[511, 148, 53],
[511, 139, 54],
[511, 130, 55],
[511, 121, 58],
[511, 112, 59],
[511, 103, 61],
[511, 94, 62],
[511, 85, 63],
[511, 76, 85],
[511, 67, 87],
[511, 58, 91],
[511, 49, 93],
[511, 40, 95],
[511, 31,109],
[511, 28,111],
[511, 19,119],
[511, 10,127],
])
assert np.array_equal(galois.bch_valid_codes(511), codes)
def test_repr():
bch = galois.BCH(15, 7)
assert repr(bch) == "<BCH Code: [15, 7, 5] over GF(2)>"


def test_bch_generator_poly_7():
Expand Down Expand Up @@ -253,47 +117,67 @@ def test_bch_generator_poly_1024():
def test_bch_properties():
bch = galois.BCH(7, 4)
assert (bch.n, bch.k, bch.t) == (7, 4, 1)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)

bch = galois.BCH(15, 11)
assert (bch.n, bch.k, bch.t) == (15, 11, 1)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(15, 7)
assert (bch.n, bch.k, bch.t) == (15, 7, 2)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(15, 5)
assert (bch.n, bch.k, bch.t) == (15, 5, 3)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)

bch = galois.BCH(31, 26)
assert (bch.n, bch.k, bch.t) == (31, 26, 1)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(31, 21)
assert (bch.n, bch.k, bch.t) == (31, 21, 2)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(31, 16)
assert (bch.n, bch.k, bch.t) == (31, 16, 3)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(31, 11)
assert (bch.n, bch.k, bch.t) == (31, 11, 5)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(31, 6)
assert (bch.n, bch.k, bch.t) == (31, 6, 7)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)

bch = galois.BCH(63, 57)
assert (bch.n, bch.k, bch.t) == (63, 57, 1)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 51)
assert (bch.n, bch.k, bch.t) == (63, 51, 2)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 45)
assert (bch.n, bch.k, bch.t) == (63, 45, 3)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 39)
assert (bch.n, bch.k, bch.t) == (63, 39, 4)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 36)
assert (bch.n, bch.k, bch.t) == (63, 36, 5)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 30)
assert (bch.n, bch.k, bch.t) == (63, 30, 6)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 24)
assert (bch.n, bch.k, bch.t) == (63, 24, 7)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 18)
assert (bch.n, bch.k, bch.t) == (63, 18,10)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 16)
assert (bch.n, bch.k, bch.t) == (63, 16,11)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 10)
assert (bch.n, bch.k, bch.t) == (63, 10,13)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)
bch = galois.BCH(63, 7)
assert (bch.n, bch.k, bch.t) == (63, 7,15)
assert (bch.is_primitive, bch.is_narrow_sense) == (True, True)


def test_bch_generator_poly_diff_primitive_poly():
Expand Down
22 changes: 21 additions & 1 deletion tests/codes/test_bch_decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import galois

from .helper import random_errors
galois.GF2,

CODES = [
(15, 11), # GF(2^4) with t=1
(15, 7), # GF(2^4) with t=2
Expand All @@ -27,6 +27,26 @@
]


def test_exceptions():
# Systematic
n, k = 15, 7
bch = galois.BCH(n, k)
GF = galois.GF2
with pytest.raises(TypeError):
bch.decode(GF.Random(n).tolist())
with pytest.raises(ValueError):
bch.decode(GF.Random(n + 1))

# Non-systematic
n, k = 15, 7
bch = galois.BCH(n, k, systematic=False)
GF = galois.GF2
with pytest.raises(TypeError):
bch.decode(GF.Random(n).tolist())
with pytest.raises(ValueError):
bch.decode(GF.Random(n - 1))


class TestSystematic:
@pytest.mark.parametrize("size", CODES)
def test_all_correctable(self, size):
Expand Down
20 changes: 20 additions & 0 deletions tests/codes/test_bch_detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@
]


def test_exceptions():
# Systematic
n, k = 15, 7
bch = galois.BCH(n, k)
GF = galois.GF2
with pytest.raises(TypeError):
bch.detect(GF.Random(n).tolist())
with pytest.raises(ValueError):
bch.detect(GF.Random(n + 1))

# Non-systematic
n, k = 15, 7
bch = galois.BCH(n, k, systematic=False)
GF = galois.GF2
with pytest.raises(TypeError):
bch.detect(GF.Random(n).tolist())
with pytest.raises(ValueError):
bch.detect(GF.Random(n - 1))


class TestSystematic:
@pytest.mark.parametrize("size", CODES)
def test_no_errors(self, size):
Expand Down
20 changes: 20 additions & 0 deletions tests/codes/test_bch_encode.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,26 @@
]


def test_exceptions():
# Systematic
n, k = 15, 7
bch = galois.BCH(n, k)
GF = galois.GF2
with pytest.raises(TypeError):
bch.encode(GF.Random(k).tolist())
with pytest.raises(ValueError):
bch.encode(GF.Random(k + 1))

# Non-systematic
n, k = 15, 7
bch = galois.BCH(n, k, systematic=False)
GF = galois.GF2
with pytest.raises(TypeError):
bch.encode(GF.Random(k).tolist())
with pytest.raises(ValueError):
bch.encode(GF.Random(k - 1))


@pytest.mark.parametrize("size", CODES)
def test_systematic(size):
n, k = size[0], size[1]
Expand Down
Loading

0 comments on commit e90642a

Please sign in to comment.