1from sympy.testing.pytest import raises
2
3from sympy import Symbol, sympify
4from sympy.polys.matrices.normalforms import invariant_factors, smith_normal_form
5from sympy.polys.domains import ZZ, QQ
6from sympy.polys.matrices import DomainMatrix
7
8
9def test_smith_normal():
10
11    def DM(elems, domain):
12        conv = lambda e: domain.from_sympy(sympify(e))
13        elems = [[conv(e) for e in row] for row in elems]
14        return DomainMatrix(elems, (len(elems), len(elems[0])), domain)
15
16    m = DM([[12, 6, 4, 8], [3, 9, 6, 12], [2, 16, 14, 28], [20, 10, 10, 20]], ZZ)
17    smf = DM([[1, 0, 0, 0], [0, 10, 0, 0], [0, 0, -30, 0], [0, 0, 0, 0]], ZZ)
18    assert smith_normal_form(m).to_dense() == smf
19
20    x = Symbol('x')
21    m = DM([[x-1,  1, -1],
22            [  0,  x, -1],
23            [  0, -1,  x]], QQ[x])
24    dx = m.domain.gens[0]
25    assert invariant_factors(m) == (1, dx-1, dx**2-1)
26
27    zr = DomainMatrix([], (0, 2), ZZ)
28    zc = DomainMatrix([[], []], (2, 0), ZZ)
29    assert smith_normal_form(zr).to_dense() == zr
30    assert smith_normal_form(zc).to_dense() == zc
31
32    assert smith_normal_form(DM([[2, 4]], ZZ)).to_dense() == DM([[2, 0]], ZZ)
33    assert smith_normal_form(DM([[0, -2]], ZZ)).to_dense() == DM([[-2, 0]], ZZ)
34    assert smith_normal_form(DM([[0], [-2]], ZZ)).to_dense() == DM([[-2], [0]], ZZ)
35
36    m =   DM([[3, 0, 0, 0], [0, 0, 0, 0], [0, 0, 2, 0]], ZZ)
37    snf = DM([[1, 0, 0, 0], [0, 6, 0, 0], [0, 0, 0, 0]], ZZ)
38    assert smith_normal_form(m).to_dense() == snf
39
40    raises(ValueError, lambda: smith_normal_form(DM([[1]], ZZ[x])))
41