def test_setitem_raises_error(self):
     """Test that setitem raises error on invalid inputs."""
     lb = LinearBinomial(5, 1)
     qt = QuadraticTrinomial(1, 2, 3)
     self.assertRaises(DegreeError, lb.__setattr__, "a", 0)
     self.assertRaises(DegreeError, qt.__setattr__, "a", 0)
     lb = LinearBinomial(5, 1)
     qt = QuadraticTrinomial(1, 2, 3)
     self.assertRaises(DegreeError, lb.__setitem__, 1, 0)
     self.assertRaises(DegreeError, qt.__setitem__, 2, 0)
 def test_trinomial_binomial_addition(self):
     """Test that QuadraticTrinomial behaves as expected."""
     a = QuadraticTrinomial(1, 2, 3)
     b = LinearBinomial(1, 2)
     e = QuadraticTrinomial(1, 3, 5)
     ep = Polynomial(e)
     # a + b is safe because a's degree does not change.
     self._assert_polynomials_are_the_same(e, a + b)
     # b + a requires a cast since b's degree does change.
     self._assert_polynomials_are_the_same(ep, b + a)
    def test_quadratic_trinomial_default_init(self):
        """Test that the default quadratic trinomial is 'x^2 + x + 1'."""
        expected = Polynomial(1, 1, 1)

        qt = QuadraticTrinomial()

        self.assertEqual(expected, qt)
    def test_quadratic_trinomial(self):
        """Test that repr() output of a QuadraticTrinomial is valid."""
        expect = "QuadraticTrinomial(1, -4, 4)"

        r = repr(QuadraticTrinomial(1, -4, 4))

        self.assertEqual(expect, r)
    def test_quadratic_trinomial_init(self):
        """Test that a quadratic trinomial is successfully initialized."""
        a, b, c = 2, 3, 4
        expected = Polynomial(a, b, c)

        qt = QuadraticTrinomial(a, b, c)

        self.assertEqual(expected, qt)
    def test_pow_by_non_integer(self):
        """Test that pow by non-integer type is not possible."""
        to_test = [
            Polynomial(1, 2, 3),
            Monomial(1, 2),
            Constant(5),
            ZeroPolynomial(),
            QuadraticTrinomial(1, 3, 7),
            LinearBinomial(9, 2),
        ]

        for val in to_test:
            self.assertRaises(ValueError, val.__pow__, 1.2)
            self.assertRaises(ValueError, val.__ipow__, 1.5)
    def test_pos(self):
        """Test that a Polynomial is equal to its positive version."""
        a = Polynomial(1, 2, 3)
        b = Monomial(1, 2)
        c = Constant(5)
        d = ZeroPolynomial()
        e = QuadraticTrinomial(1, 3, 7)
        f = LinearBinomial(9, 2)

        self._assert_polynomials_are_the_same(a, +a)
        self._assert_polynomials_are_the_same(b, +b)
        self._assert_polynomials_are_the_same(c, +c)
        self._assert_polynomials_are_the_same(d, +d)
        self._assert_polynomials_are_the_same(e, +e)
        self._assert_polynomials_are_the_same(f, +f)
    def test_div_by_zero(self):
        """Test that division by 0 is not possible."""
        to_test = [
            Polynomial(1, 2, 3),
            Monomial(1, 2),
            Constant(5),
            ZeroPolynomial(),
            QuadraticTrinomial(1, 3, 7),
            LinearBinomial(9, 2),
        ]

        for val in to_test:
            self.assertRaises(ZeroDivisionError, val.__floordiv__, 0)
            self.assertRaises(ZeroDivisionError, val.__ifloordiv__, 0)
            self.assertRaises(ZeroDivisionError, val.__mod__, 0)
            self.assertRaises(ZeroDivisionError, val.__imod__, 0)
            self.assertRaises(ZeroDivisionError, val.__divmod__, 0)
    def test_inequality(self):
        """Test that distinct values do not equal other."""
        to_test = [
            Polynomial(1, 2, 3),
            Monomial(1, 2),
            Constant(5),
            ZeroPolynomial(),
            QuadraticTrinomial(1, 3, 7),
            LinearBinomial(9, 2), 7
        ]

        for i, lhs in enumerate(to_test):
            for j, rhs in enumerate(to_test):
                if i == j:
                    self.assertTrue(lhs == lhs)
                    self.assertFalse(lhs != lhs)
                else:
                    self.assertFalse(lhs == rhs)
                    self.assertNotEqual(lhs, rhs)
    def test_zero_discriminant_roots(self):
        """Test the real and complex roots and factors for D == 0."""
        qt = QuadraticTrinomial(1, 4, 4)
        exp_discri = 0
        exp_real_roots = (-2, -2)
        exp_complex_roots = (-2, -2)
        exp_real_factors = (1, LinearBinomial(1, 2), LinearBinomial(1, 2))
        exp_complex_factors = exp_real_factors

        res_discri = qt.discriminant
        res_real_roots = qt.real_roots
        res_complex_roots = qt.complex_roots
        res_real_factors = qt.real_factors
        res_complex_factors = qt.complex_factors

        self.assertEqual(exp_discri, res_discri)
        self.assertEqual(exp_real_roots, res_real_roots)
        self.assertEqual(exp_complex_roots, res_complex_roots)
        self.assertEqual(exp_real_factors, res_real_factors)
        self.assertEqual(exp_complex_factors, res_complex_factors)
    def test_positive_discriminant_roots(self):
        """Test the real and complex roots and factors for D > 0."""
        qt = QuadraticTrinomial(1, -5, 6)
        exp_discri = 1
        exp_real_roots = (3, 2)
        exp_complex_roots = (3, 2)
        exp_real_factors = (1, LinearBinomial(1, -3), LinearBinomial(1, -2))
        exp_complex_factors = exp_real_factors

        res_discri = qt.discriminant
        res_real_roots = qt.real_roots
        res_complex_roots = qt.complex_roots
        res_real_factors = qt.real_factors
        res_complex_factors = qt.complex_factors

        self.assertEqual(exp_discri, res_discri)
        self.assertEqual(exp_real_roots, res_real_roots)
        self.assertEqual(exp_complex_roots, res_complex_roots)
        self.assertEqual(exp_real_factors, res_real_factors)
        self.assertEqual(exp_complex_factors, res_complex_factors)
    def test_setting_empty_terms_immutable_degree(self):
        """Test setting empty terms."""
        immutable = [
            QuadraticTrinomial(1, 2, 3),
            LinearBinomial(1, 2),
        ]

        for val in immutable:
            self.assertRaises(DegreeError, val.__setattr__, "terms", [])

        try:
            a = Constant(0)
            a.terms = []
            a = Constant(5)
            a.terms = []
        except DegreeError:
            self.assertFalse(True,
                             "Should be able to set Constant(0).terms to []")

        a = Constant(1)
        a.terms = []
    def test_negative_discriminant_roots(self):
        """Test the real and complex roots and factors for D < 0."""
        qt = QuadraticTrinomial(1, 2, 5)
        exp_discri = -16
        exp_real_roots = ()
        exp_complex_roots = (-1 + 2j, -1 - 2j)
        exp_real_factors = (qt, )
        exp_complex_factors = (1, LinearBinomial(1, 1 - 2j),
                               LinearBinomial(1, 1 + 2j))

        res_discri = qt.discriminant
        res_real_roots = qt.real_roots
        res_complex_roots = qt.complex_roots
        res_real_factors = qt.real_factors
        res_complex_factors = qt.complex_factors

        self.assertEqual(exp_discri, res_discri)
        self.assertEqual(exp_real_roots, res_real_roots)
        self.assertEqual(exp_complex_roots, res_complex_roots)
        self.assertEqual(exp_real_factors, res_real_factors)
        self.assertEqual(exp_complex_factors, res_complex_factors)
    def test_ipow_zero_gives_one(self):
        """Test that x **= 0 returns an appropriate 1 polynomial."""
        to_test = [
            Polynomial(1, 2, 3),
            Monomial(1, 2),
            Constant(5),
            ZeroPolynomial(),
            QuadraticTrinomial(1, 3, 7),
            LinearBinomial(9, 2),
        ]

        one_maps = {
            Polynomial: Polynomial(1),
            Monomial: Monomial(1, 0),
            Constant: Constant(1),
            ZeroPolynomial: Constant(1),
            QuadraticTrinomial: Polynomial(1),
            LinearBinomial: Polynomial(1),
        }

        for val in to_test:
            expected = one_maps[type(val)]
            val **= 0
            self._assert_polynomials_are_the_same(expected, val)