def test_collapse_to_one_poly(): IntMod.modulus = 5 p = PolyMod([ IntMod(1), IntMod(0), IntMod(0), IntMod(0), IntMod(0), IntMod(0), IntMod(0) ]) p.collapse_degree() expected_p = PolyMod([IntMod(1)]) assert p == expected_p
def test_create_with_coefs(): IntMod.modulus = 5 p = PolyMod([IntMod(2)]) assert p.coef_list == [IntMod(2)] assert p.degree == 0
def test_collapse_degree_all_zeros(): IntMod.modulus = 5 p = PolyMod([ IntMod(0), IntMod(0), IntMod(0), IntMod(0), IntMod(0), IntMod(0), IntMod(0) ]) p.collapse_degree() expected_p = PolyMod([IntMod(0)]) assert p == expected_p
def test_create_with_quotient(): IntMod.modulus = 7 qp = PolyMod([IntMod(1), IntMod(2), IntMod(1)]) RemainderPoly.quotient = qp rp = RemainderPoly([IntMod(1), IntMod(4), IntMod(6), IntMod(4), IntMod(1)]) rp._residue() # pylint: disable=protected-access x = str(rp) assert x == '0'
def test_create(): IntMod.modulus = 5 p = PolyMod() assert p.coef_list == [] with pytest.raises(ValueError, match='Degree of null polynomial undefined.'): # noinspection PyStatementEffect p.degree # pylint: disable=pointless-statement
def test_times_no_residue_needed(): IntMod.modulus = 3 qp = PolyMod([IntMod(1), IntMod(1), IntMod(1), IntMod(1)]) RemainderPoly.quotient = qp rp1 = RemainderPoly(coef_list=[IntMod(1), IntMod(1)]) rp2 = RemainderPoly(coef_list=[IntMod(1), IntMod(1)]) rp = rp1 * rp2 rp_expected = RemainderPoly(coef_list=[IntMod(1), IntMod(2), IntMod(1)]) assert rp == rp_expected
class RemainderPoly(PolyMod): quotient = PolyMod() def __repr__(self) -> str: return f"RemainderPoly(coef_list={self.coef_list})" def __add__(self, operand: 'RemainderPoly') -> 'RemainderPoly': coef_tuples = itertools.zip_longest(self, operand, fillvalue=IntMod(0)) result_coefs = [a + b for a, b in coef_tuples] result = RemainderPoly(result_coefs) result.collapse_degree() return result def __mul__(self, operand: 'RemainderPoly') -> 'RemainderPoly': result_degree = self.degree + operand.degree result = RemainderPoly(coef_list=[IntMod(0)] * (result_degree + 1)) for k in range(result_degree + 1): min_index = k - operand.degree if k - operand.degree > 0 else 0 max_index = k if k < self.degree else self.degree for m in range(min_index, max_index + 1): # pylint: disable=invalid-name result[k] = result[k] + self[m] * operand[k - m] result._residue() return result def _residue(self): qdegree = len(RemainderPoly.quotient) - \ 1 if RemainderPoly.quotient.coef_list else -1 if qdegree > 0: while self.degree >= qdegree: factor = self[self.degree] // RemainderPoly.quotient[qdegree] for qindex in range(0, qdegree + 1): cindex = self.degree - qdegree + qindex self[cindex] = self[cindex] - factor * \ RemainderPoly.quotient[qindex] self.collapse_degree() @classmethod def constant(cls, value: int) -> 'RemainderPoly': return cls([IntMod(value)])
def test_degree(): IntMod.modulus = 5 p = PolyMod([IntMod(2), IntMod(3), IntMod(0), IntMod(1), IntMod(4)]) assert p.degree == 4
def test_enumerate(): IntMod.modulus = 5 p = PolyMod([IntMod(2), IntMod(3), IntMod(4)]) assert p.enumerate() == 117
def test_str_one_handling(): IntMod.modulus = 5 p = PolyMod([IntMod(1), IntMod(1), IntMod(1)]) assert str(p) == "x^2 + x + 1"
def test_str_zero_handling(): IntMod.modulus = 5 p = PolyMod([IntMod(0), IntMod(0), IntMod(0), IntMod(4)]) assert str(p) == "4x^3"
def test_str_one_poly(): IntMod.modulus = 5 p = PolyMod([IntMod(1)]) assert str(p) == "1"
def test_str_degree_zero(): IntMod.modulus = 5 p = PolyMod([IntMod(2)]) assert str(p) == "2"
def test_str_zero_poly(): IntMod.modulus = 5 p = PolyMod([IntMod(0)]) assert str(p) == "0"
def test_str(): IntMod.modulus = 5 p = PolyMod([IntMod(2), IntMod(3), IntMod(0), IntMod(1), IntMod(4)]) assert str(p) == "4x^4 + x^3 + 3x + 2"
def test_evaluate(): IntMod.modulus = 5 p = PolyMod([IntMod(2), IntMod(3), IntMod(4)]) assert p(IntMod(3)) == IntMod(2)
def test_reducible_false(): IntMod.modulus = 5 p = PolyMod([IntMod(2), IntMod(3), IntMod(4)]) assert not p.is_reducible()
def test_reducible_factors(): IntMod.modulus = 5 p = PolyMod([IntMod(1), IntMod(2), IntMod(1)]) assert p.is_reducible()
def test_reducible_true(): IntMod.modulus = 5 p = PolyMod([IntMod(0), IntMod(1)]) assert p.is_reducible()