Skip to content

Commit

Permalink
Change max line length to 120
Browse files Browse the repository at this point in the history
  • Loading branch information
mhostetter committed Feb 1, 2023
1 parent 41b17f0 commit 100363b
Show file tree
Hide file tree
Showing 52 changed files with 1,376 additions and 914 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
},
"editor.rulers": [
120
]
}
14 changes: 11 additions & 3 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,11 @@ def autodoc_skip_member(app, what, name, obj, skip, options):
elif getattr(obj, "__qualname__", None) in ["FunctionMixin.dot", "Array.astype"]:
# NumPy methods that were overridden, don't include docs
return True
elif hasattr(obj, "__qualname__") and getattr(obj, "__qualname__").split(".")[0] == "FieldArray" and hasattr(numpy.ndarray, name):
elif (
hasattr(obj, "__qualname__")
and getattr(obj, "__qualname__").split(".")[0] == "FieldArray"
and hasattr(numpy.ndarray, name)
):
if name in ["__repr__", "__str__"]:
# Specifically allow these methods to be documented
return False
Expand Down Expand Up @@ -356,7 +360,9 @@ def classproperty(obj):
return ret


ArrayMeta_properties = [member for member in dir(galois.Array) if inspect.isdatadescriptor(getattr(type(galois.Array), member, None))]
ArrayMeta_properties = [
member for member in dir(galois.Array) if inspect.isdatadescriptor(getattr(type(galois.Array), member, None))
]
for p in ArrayMeta_properties:
# Fetch the class properties from the private metaclasses
ArrayMeta_property = getattr(galois._domains._meta.ArrayMeta, p)
Expand All @@ -372,7 +378,9 @@ def classproperty(obj):


FieldArrayMeta_properties = [
member for member in dir(galois.FieldArray) if inspect.isdatadescriptor(getattr(type(galois.FieldArray), member, None))
member
for member in dir(galois.FieldArray)
if inspect.isdatadescriptor(getattr(type(galois.FieldArray), member, None))
]
for p in FieldArrayMeta_properties:
# Fetch the class properties from the private metaclasses
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ disable = [
"unneeded-not",
]
min-similarity-lines = 100
max-line-length = 140
max-line-length = 120

[tool.black]
line-length = 140
line-length = 120
exclude = '''
/(
build
Expand Down
12 changes: 9 additions & 3 deletions scripts/create_prime_factors_database.py
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,9 @@ def parse_factors_string(table: dict, rows: dict, row: dict, string: str, letter
# A special composite. Verify that it divides the remaining value.
label = prime_composite_label(table, row["n"], letter)
key = (label, factor)
assert row["composite"] % table["composites"][key] == 0, f"{row['composite']} is not divisible by {table['composites'][key]}"
assert (
row["composite"] % table["composites"][key] == 0
), f"{row['composite']} is not divisible by {table['composites'][key]}"
else:
# Must be a regular integer
factor = int(factor)
Expand Down Expand Up @@ -443,7 +445,9 @@ def add_to_database(
)


def test_factorization(base: int, exponent: int, offset: int, value: int, factors: list[int], multiplicities: list[int], composite: int):
def test_factorization(
base: int, exponent: int, offset: int, value: int, factors: list[int], multiplicities: list[int], composite: int
):
"""
Tests that all the factorization parameters are consistent.
"""
Expand Down Expand Up @@ -494,7 +498,9 @@ def create_even_negative_offset_table(conn: sqlite3.Connection, cursor: sqlite3.

row = select_two_factorizations_from_database(cursor, A_value, B_value)
if row is None:
assert k == k_fail, f"The {base}^(2k) - 1 table generation failed at k = {k}, but should have failed at k = {k_fail}"
assert (
k == k_fail
), f"The {base}^(2k) - 1 table generation failed at k = {k}, but should have failed at k = {k_fail}"
break

exponent = 2 * k
Expand Down
36 changes: 34 additions & 2 deletions scripts/generate_field_test_vectors.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,23 @@ def make_luts(field, sub_folder, seed, sparse=False):
save_pickle(d, folder, "matrix_inverse.pkl")

set_seed(seed + 206)
shapes = [(2, 2), (2, 2), (2, 2), (3, 3), (3, 3), (3, 3), (4, 4), (4, 4), (4, 4), (5, 5), (5, 5), (5, 5), (6, 6), (6, 6), (6, 6)]
shapes = [
(2, 2),
(2, 2),
(2, 2),
(3, 3),
(3, 3),
(3, 3),
(4, 4),
(4, 4),
(4, 4),
(5, 5),
(5, 5),
(5, 5),
(6, 6),
(6, 6),
(6, 6),
]
X = []
Z = []
for i in range(len(shapes)):
Expand All @@ -488,7 +504,23 @@ def make_luts(field, sub_folder, seed, sparse=False):
save_pickle(d, folder, "matrix_determinant.pkl")

set_seed(seed + 207)
shapes = [(2, 2), (2, 2), (2, 2), (3, 3), (3, 3), (3, 3), (4, 4), (4, 4), (4, 4), (5, 5), (5, 5), (5, 5), (6, 6), (6, 6), (6, 6)]
shapes = [
(2, 2),
(2, 2),
(2, 2),
(3, 3),
(3, 3),
(3, 3),
(4, 4),
(4, 4),
(4, 4),
(5, 5),
(5, 5),
(5, 5),
(6, 6),
(6, 6),
(6, 6),
]
X = []
Y = []
Z = []
Expand Down
3 changes: 2 additions & 1 deletion src/galois/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
__version__ = "0.0.0"
__version_tuple__ = (0, 0, 0)
warnings.warn(
"An error occurred during package install where setuptools_scm failed to create a _version.py file. Defaulting version to 0.0.0."
"An error occurred during package install where setuptools_scm failed to create a _version.py file."
"Defaulting version to 0.0.0."
)

# Import class/functions from nested private modules
Expand Down
92 changes: 52 additions & 40 deletions src/galois/_codes/_bch.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ class BCH(_CyclicCode):
.. info::
:title: Shortened codes
To create the shortened :math:`\textrm{BCH}(n-s, k-s)` code, construct the full-sized :math:`\textrm{BCH}(n, k)` code
and then pass :math:`k-s` symbols into :func:`encode` and :math:`n-s` symbols into :func:`decode()`. Shortened codes are only
applicable for systematic codes.
To create the shortened :math:`\textrm{BCH}(n-s, k-s)` code, construct the full-sized
:math:`\textrm{BCH}(n, k)` code and then pass :math:`k-s` symbols into :func:`encode` and :math:`n-s` symbols
into :func:`decode()`. Shortened codes are only applicable for systematic codes.
A BCH code is a cyclic code over :math:`\mathrm{GF}(q)` with generator polynomial :math:`g(x)`. The generator polynomial is over
:math:`\mathrm{GF}(q)` and has :math:`d-1` roots :math:`\alpha^c, \dots, \alpha^{c+d-2}` when evaluated in :math:`\mathrm{GF}(q^m)`.
The element :math:`\alpha` is a primitive :math:`n`-th root of unity in :math:`\mathrm{GF}(q^m)`.
A BCH code is a cyclic code over :math:`\mathrm{GF}(q)` with generator polynomial :math:`g(x)`. The generator
polynomial is over :math:`\mathrm{GF}(q)` and has :math:`d-1` roots :math:`\alpha^c, \dots, \alpha^{c+d-2}` when
evaluated in :math:`\mathrm{GF}(q^m)`. The element :math:`\alpha` is a primitive :math:`n`-th root of unity in
:math:`\mathrm{GF}(q^m)`.
.. math::
Expand Down Expand Up @@ -100,19 +101,21 @@ def __init__(
Arguments:
n: The codeword size :math:`n`. If :math:`n = q^m - 1`, the BCH code is *primitive*.
k: The message size :math:`k`.
d: The design distance :math:`d`. This defines the number of roots :math:`d - 1` in the generator polynomial
:math:`g(x)` over :math:`\mathrm{GF}(q^m)`.
field: The Galois field :math:`\mathrm{GF}(q)` that defines the alphabet of the codeword symbols. The default
is `None` which corresponds to :math:`\mathrm{GF}(2)`.
extension_field: The Galois field :math:`\mathrm{GF}(q^m)` that defines the syndrome arithmetic. The default is
`None` which corresponds to :math:`\mathrm{GF}(q^m)` where :math:`q^{m - 1} \le n < q^m`. The default extension
field will use `matlab_primitive_poly(q, m)` for the irreducible polynomial.
d: The design distance :math:`d`. This defines the number of roots :math:`d - 1` in the generator
polynomial :math:`g(x)` over :math:`\mathrm{GF}(q^m)`.
field: The Galois field :math:`\mathrm{GF}(q)` that defines the alphabet of the codeword symbols.
The default is `None` which corresponds to :math:`\mathrm{GF}(2)`.
extension_field: The Galois field :math:`\mathrm{GF}(q^m)` that defines the syndrome arithmetic.
The default is `None` which corresponds to :math:`\mathrm{GF}(q^m)` where
:math:`q^{m - 1} \le n < q^m`. The default extension field will use `matlab_primitive_poly(q, m)`
for the irreducible polynomial.
alpha: A primitive :math:`n`-th root of unity :math:`\alpha` in :math:`\mathrm{GF}(q^m)` that defines the
:math:`\alpha^c, \dots, \alpha^{c+d-2}` roots of the generator polynomial :math:`g(x)`.
c: The first consecutive power :math:`c` of :math:`\alpha` that defines the :math:`\alpha^c, \dots, \alpha^{c+d-2}`
roots of the generator polynomial :math:`g(x)`. The default is 1. If :math:`c = 1`, the BCH code is *narrow-sense*.
systematic: Indicates if the encoding should be systematic, meaning the codeword is the message with parity appended.
The default is `True`.
c: The first consecutive power :math:`c` of :math:`\alpha` that defines the
:math:`\alpha^c, \dots, \alpha^{c+d-2}` roots of the generator polynomial :math:`g(x)`.
The default is 1. If :math:`c = 1`, the BCH code is *narrow-sense*.
systematic: Indicates if the encoding should be systematic, meaning the codeword is the message with
parity appended. The default is `True`.
See Also:
matlab_primitive_poly, FieldArray.primitive_root_of_unity
Expand Down Expand Up @@ -170,7 +173,8 @@ def __init__(
field = GF2
if not field.is_prime_field:
raise ValueError(
"Current BCH codes over GF(q) for prime power q are not supported. Proper Galois field towers are needed first."
"Current BCH codes over GF(q) for prime power q are not supported. "
"Proper Galois field towers are needed first."
)
q = field.order # The size of the codeword alphabet

Expand Down Expand Up @@ -496,19 +500,20 @@ def decode(
{},
r"""
In decoding, the syndrome vector :math:`\mathbf{s}` is computed by evaluating the received codeword
:math:`\mathbf{r}` in the extension field :math:`\mathrm{GF}(q^m)` at the roots :math:`\alpha^c, \dots, \alpha^{c+d-2}`
of the generator polynomial :math:`g(x)`. The equivalent polynomial operation computes the remainder
of :math:`r(x)` by :math:`g(x)` in the extension field :math:`\mathrm{GF}(q^m)`.
:math:`\mathbf{r}` in the extension field :math:`\mathrm{GF}(q^m)` at the roots
:math:`\alpha^c, \dots, \alpha^{c+d-2}` of the generator polynomial :math:`g(x)`. The equivalent polynomial
operation computes the remainder of :math:`r(x)` by :math:`g(x)` in the extension field
:math:`\mathrm{GF}(q^m)`.
.. math::
\mathbf{s} = [r(\alpha^c),\ \dots,\ r(\alpha^{c+d-2})] \in \mathrm{GF}(q^m)^{d-1}
.. math::
s(x) = r(x)\ \textrm{mod}\ g(x) \in \mathrm{GF}(q^m)[x]
A syndrome of zeros indicates the received codeword is a valid codeword and there are no errors. If the syndrome
is non-zero, the decoder will find an error-locator polynomial :math:`\sigma(x)` and the corresponding error
locations and values.
A syndrome of zeros indicates the received codeword is a valid codeword and there are no errors. If the
syndrome is non-zero, the decoder will find an error-locator polynomial :math:`\sigma(x)` and the corresponding
error locations and values.
Note:
The :math:`[n, k, d]_q` code has :math:`d_{min} \ge d` minimum distance. It can detect up
Expand Down Expand Up @@ -592,7 +597,8 @@ def decode(
m = GF.Random((3, bch.k)); m
c = bch.encode(m); c
Corrupt the codeword. Add zero errors to the first codeword, one to the second, and two to the third.
Corrupt the codeword. Add zero errors to the first codeword, one to the second, and two to the
third.
.. ipython:: python
Expand Down Expand Up @@ -625,7 +631,8 @@ def decode(
m = GF.Random((3, bch.k - 3)); m
c = bch.encode(m); c
Corrupt the codeword. Add zero errors to the first codeword, one to the second, and two to the third.
Corrupt the codeword. Add zero errors to the first codeword, one to the second, and two to the
third.
.. ipython:: python
Expand All @@ -652,7 +659,8 @@ def decode(self, codeword, output="message", errors=False):
return super().decode(codeword, output=output, errors=errors)

def _decode_codeword(self, codeword: FieldArray) -> tuple[FieldArray, np.ndarray]:
dec_codeword, N_errors = decode_jit(self.field, self.extension_field)(codeword, self.n, int(self.alpha), self.c, self.roots)
func = decode_jit(self.field, self.extension_field)
dec_codeword, N_errors = func(codeword, self.n, int(self.alpha), self.c, self.roots)
dec_codeword = dec_codeword.view(self.field)
return dec_codeword, N_errors

Expand Down Expand Up @@ -929,8 +937,8 @@ def alpha(self) -> FieldArray:
@property
def c(self) -> int:
r"""
The first consecutive power :math:`c` of :math:`\alpha` that defines the roots :math:`\alpha^c, \dots, \alpha^{c+d-2}`
of the generator polynomial :math:`g(x)`.
The first consecutive power :math:`c` of :math:`\alpha` that defines the roots
:math:`\alpha^c, \dots, \alpha^{c+d-2}` of the generator polynomial :math:`g(x)`.
Examples:
Construct a binary narrow-sense :math:`\textrm{BCH}(15, 7)` code with first consecutive root
Expand Down Expand Up @@ -1141,8 +1149,8 @@ def _generator_poly_from_k(
# This d is too small to produce the BCH code
possible_d = possible_d[idx + 1 :]
elif generator_poly.degree == n - k:
# This d produces the correct BCH code size and g(x) is its generator. However, there may also be a larger d that
# generates a BCH code of the same size, so keep looking.
# This d produces the correct BCH code size and g(x) is its generator. However, there may also be a
# larger d that generates a BCH code of the same size, so keep looking.
break
else:
# This d is too large to produce the BCH code
Expand Down Expand Up @@ -1195,7 +1203,8 @@ def __call__(self, codeword, design_n, alpha, c, roots):

def set_globals(self):
# pylint: disable=global-variable-undefined
global CHARACTERISTIC, SUBTRACT, MULTIPLY, RECIPROCAL, POWER, CONVOLVE, POLY_ROOTS, POLY_EVALUATE, BERLEKAMP_MASSEY
global CHARACTERISTIC, SUBTRACT, MULTIPLY, RECIPROCAL, POWER
global CONVOLVE, POLY_ROOTS, POLY_EVALUATE, BERLEKAMP_MASSEY

SUBTRACT = self.field._subtract.ufunc_call_only

Expand Down Expand Up @@ -1231,14 +1240,15 @@ def implementation(codewords, design_n, alpha, c, roots): # pragma: no cover
continue

# The error pattern is defined as the polynomial e(x) = e_j1*x^j1 + e_j2*x^j2 + ... for j1 to jv,
# implying there are v errors. And δi = e_ji is the i-th error value and βi = α^ji is the i-th error-locator
# value and ji is the error location.
# implying there are v errors. And δi = e_ji is the i-th error value and βi = α^ji is the i-th
# error-locator value and ji is the error location.

# The error-locator polynomial σ(x) = (1 - β1*x)(1 - β2*x)...(1 - βv*x) where βi are the inverse of the roots
# of σ(x).
# The error-locator polynomial σ(x) = (1 - β1*x)(1 - β2*x)...(1 - βv*x) where βi are the inverse of the
# roots of σ(x).

# Compute the error-locator polynomial σ(x)
# TODO: Re-evaluate these equations since changing BMA to return characteristic polynomial, not feedback polynomial
# TODO: Re-evaluate these equations since changing BMA to return the characteristic polynomial,
# not the feedback polynomial
sigma = BERLEKAMP_MASSEY(syndrome)[::-1]
v = sigma.size - 1 # The number of errors, which is the degree of the error-locator polynomial

Expand All @@ -1254,8 +1264,8 @@ def implementation(codewords, design_n, alpha, c, roots): # pragma: no cover
error_locations = -error_locations_inv % design_n # The error locations as degrees of c(x)

if np.any(error_locations > n - 1):
# Indicates there are "errors" in the zero-ed portion of a shortened code, which indicates there are actually
# more errors than alleged. Return failure to decode.
# Indicates there are "errors" in the zero-ed portion of a shortened code, which indicates there are
# actually more errors than alleged. Return failure to decode.
dec_codewords[i, -1] = -1
continue

Expand Down Expand Up @@ -1283,7 +1293,9 @@ def implementation(codewords, design_n, alpha, c, roots): # pragma: no cover
delta_i = MULTIPLY(beta_i, Z0_i)
delta_i = MULTIPLY(delta_i, RECIPROCAL(sigma_prime_i))
delta_i = SUBTRACT(0, delta_i)
dec_codewords[i, n - 1 - error_locations[j]] = SUBTRACT(dec_codewords[i, n - 1 - error_locations[j]], delta_i)
dec_codewords[i, n - 1 - error_locations[j]] = SUBTRACT(
dec_codewords[i, n - 1 - error_locations[j]], delta_i
)

dec_codewords[i, -1] = v # The number of corrected errors

Expand Down
3 changes: 2 additions & 1 deletion src/galois/_codes/_cyclic.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ def __init__(
self._roots = roots

# Calculate the parity-check polynomial h(x) = (x^n - 1) / g(x)
parity_check_poly, remainder_poly = divmod(Poly.Degrees([n, 0], [1, -1], field=generator_poly.field), generator_poly)
f = Poly.Degrees([n, 0], [1, -1], field=generator_poly.field)
parity_check_poly, remainder_poly = divmod(f, generator_poly)
assert remainder_poly == 0
self._parity_check_poly = parity_check_poly

Expand Down
Loading

0 comments on commit 100363b

Please sign in to comment.