Skip to content

Commit 13a6928

Browse files
Merge pull request #76 from kamalsaleh/main
Add LaTeXOutputOfHomalg(Matrix/Ring/Element)
2 parents 91f6257 + f535b55 commit 13a6928

5 files changed

Lines changed: 296 additions & 1 deletion

File tree

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "MatricesForHomalg"
22
uuid = "29b9b1b6-efa6-450e-8188-a5a2c25df071"
3-
version = "0.1.11"
3+
version = "0.1.12"
44
authors = ["Mohamed Barakat <mohamed.barakat@uni-siegen.de>", "Johanna Knecht <johanna.knecht@student.uni-siegen.de>"]
55

66
[deps]

ext/MatricesForHomalgSingularExt.jl

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,6 +1407,163 @@ function MatricesForHomalg.ReducedSyzygiesOfRows(A::Singular.smatrix, N::Singula
14071407
return Singular.transpose(MatricesForHomalg.ReducedSyzygiesOfColumns(Singular.transpose(A), Singular.transpose(N)))
14081408
end
14091409

1410+
## LaTeX output for Singular rings and matrices
1411+
1412+
"""
1413+
LaTeXOutputOfHomalgRing(R::Singular.Integers)
1414+
1415+
Return `"\\mathbb{Z}"` for the Singular integer ring.
1416+
1417+
```jldoctest
1418+
julia> using Singular, MatricesForHomalg
1419+
1420+
julia> LaTeXOutputOfHomalgRing(HomalgRingOfIntegersInSingular())
1421+
"\\mathbb{Z}"
1422+
```
1423+
"""
1424+
function MatricesForHomalg.LaTeXOutputOfHomalgRing(::Singular.Integers)::String
1425+
return "\\mathbb{Z}"
1426+
end
1427+
1428+
"""
1429+
LaTeXOutputOfHomalgRing(R::Singular.Rationals)
1430+
1431+
Return `"\\mathbb{Q}"` for the Singular rational field.
1432+
1433+
```jldoctest
1434+
julia> using Singular, MatricesForHomalg
1435+
1436+
julia> LaTeXOutputOfHomalgRing(HomalgFieldOfRationalsInSingular())
1437+
"\\mathbb{Q}"
1438+
```
1439+
"""
1440+
function MatricesForHomalg.LaTeXOutputOfHomalgRing(::Singular.Rationals)::String
1441+
return "\\mathbb{Q}"
1442+
end
1443+
1444+
"""
1445+
LaTeXOutputOfHomalgRing(R::Singular.PolyRing)
1446+
1447+
Return a LaTeX string for the Singular polynomial ring R.
1448+
1449+
```jldoctest
1450+
julia> using Singular, MatricesForHomalg
1451+
1452+
julia> R, _ = Singular.polynomial_ring(Singular.QQ, ["x", "y"]);
1453+
1454+
julia> LaTeXOutputOfHomalgRing(R)
1455+
"\\\\mathbb{Q}[x, y]"
1456+
1457+
julia> S = R / [R("x^2 + y^2 - 1")];
1458+
1459+
julia> LaTeXOutputOfHomalgRing(S)
1460+
"\\\\mathbb{Q}[x, y] / ( x^2 + y^2 - 1 )"
1461+
```
1462+
"""
1463+
function MatricesForHomalg.LaTeXOutputOfHomalgRing(R::Singular.PolyRing)::String
1464+
base_latex = LaTeXOutputOfHomalgRing(Singular.base_ring(R))
1465+
vars = join(map(s -> string(s), R.S), ", ")
1466+
name = base_latex * "[" * vars * "]"
1467+
if Singular.is_quotient_ring(R)
1468+
I = Singular.quotient_ideal(R)
1469+
rels = join([string(Singular.gens(I)[k]) for k in 1:Singular.ngens(I)], ", ")
1470+
name *= " / ( " * rels * " )"
1471+
end
1472+
return name
1473+
end
1474+
1475+
function MatricesForHomalg._latex_entry(x::Singular.spoly)::String
1476+
Singular.iszero(x) && return "\\cdot"
1477+
return MatricesForHomalg.LaTeXOutputOfHomalgRingElement(x)
1478+
end
1479+
1480+
# Build a monomial string from variable symbols and exponent vector.
1481+
# Uses ^{n} for exponents > 1, no separator between variables.
1482+
function _latex_monomial(syms::Vector{Symbol}, exps::Vector{Int})::String
1483+
factors = String[]
1484+
for (s, e) in zip(syms, exps)
1485+
e == 0 && continue
1486+
e == 1 ? push!(factors, string(s)) : push!(factors, "$(s)^{$(e)}")
1487+
end
1488+
return join(factors, "")
1489+
end
1490+
1491+
# Returns (absolute_value_latex, is_negative) for a Singular integer coefficient.
1492+
function _latex_singular_coeff(c::Singular.n_Z)
1493+
n = BigInt(c)
1494+
return (string(abs(n)), n < 0)
1495+
end
1496+
1497+
# Returns (absolute_value_latex, is_negative) for a Singular rational coefficient.
1498+
function _latex_singular_coeff(c::Singular.n_Q)
1499+
n = BigInt(numerator(c))
1500+
d = BigInt(denominator(c))
1501+
neg = n < 0
1502+
an = abs(n)
1503+
d == 1 && return (string(an), neg)
1504+
return ("\\frac{$(an)}{$(d)}", neg)
1505+
end
1506+
1507+
# Fallback for other coefficient types.
1508+
function _latex_singular_coeff(c)
1509+
s = string(c)
1510+
startswith(s, "-") && return (s[2:end], true)
1511+
return (s, false)
1512+
end
1513+
1514+
"""
1515+
LaTeXOutputOfHomalgRingElement(f::Singular.spoly)
1516+
1517+
Return a LaTeX string for the Singular polynomial f, built from its internal
1518+
term structure: monomials use `^{n}` for exponents, rational coefficients use
1519+
`\\frac`, coefficient ±1 on non-constant monomials is suppressed, and terms
1520+
are joined with ` + ` / ` - `.
1521+
1522+
```jldoctest
1523+
julia> using Singular, MatricesForHomalg
1524+
1525+
julia> R, (x, y) = Singular.polynomial_ring(Singular.QQ, ["x", "y"]);
1526+
1527+
julia> LaTeXOutputOfHomalgRingElement(x^2 + 2*y)
1528+
"x^{2} + 2y"
1529+
1530+
julia> LaTeXOutputOfHomalgRingElement(QQ(1,3)*x - QQ(1,2)*y^2)
1531+
"\\\\frac{1}{3}x - \\\\frac{1}{2}y^{2}"
1532+
1533+
julia> LaTeXOutputOfHomalgRingElement(zero(R))
1534+
"0"
1535+
1536+
julia> LaTeXOutputOfHomalgRingElement(one(R))
1537+
"1"
1538+
```
1539+
"""
1540+
function MatricesForHomalg.LaTeXOutputOfHomalgRingElement(f::Singular.spoly)::String
1541+
Singular.iszero(f) && return "0"
1542+
R = parent(f)
1543+
syms = R.S
1544+
result = ""
1545+
first_term = true
1546+
for (c, exps) in zip(Singular.coefficients(f), Singular.exponent_vectors(f))
1547+
mon = _latex_monomial(syms, exps)
1548+
coeff_latex, neg = _latex_singular_coeff(c)
1549+
is_one = (coeff_latex == "1")
1550+
term = if isempty(mon)
1551+
coeff_latex # constant term: show the absolute coefficient
1552+
elseif is_one
1553+
mon # coefficient ±1: show only the monomial
1554+
else
1555+
coeff_latex * mon # general: coefficient immediately before monomial
1556+
end
1557+
if first_term
1558+
result = neg ? "-$(term)" : term
1559+
first_term = false
1560+
else
1561+
result *= neg ? " - $(term)" : " + $(term)"
1562+
end
1563+
end
1564+
return result
1565+
end
1566+
14101567
## Ring membership for Singular polynomial rings
14111568
#
14121569
# In GAP, `r in Ring` checks if r is an element of Ring. Julia's generic `in`

src/MatricesForHomalg.jl

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -848,9 +848,114 @@ function StringDisplay(mat)::String
848848
string(mat)
849849
end
850850

851+
function _latex_entry(x::Nemo.ZZRingElem)::String
852+
Nemo.iszero(x) && return "\\cdot"
853+
return string(x)
854+
end
855+
856+
function _latex_entry(x::Nemo.QQFieldElem)::String
857+
Nemo.iszero(x) && return "\\cdot"
858+
d = Nemo.denominator(x)
859+
if Nemo.isone(d)
860+
return string(Nemo.numerator(x))
861+
end
862+
n = Nemo.numerator(x)
863+
if n < 0
864+
return "-\\frac{$(abs(n))}{$(d)}"
865+
end
866+
return "\\frac{$(n)}{$(d)}"
867+
end
868+
869+
"""
870+
LaTeXOutputOfHomalgRingElement(x)
871+
872+
Return a LaTeX string for the ring element x.
873+
874+
```jldoctest
875+
julia> LaTeXOutputOfHomalgRingElement(ZZ(0))
876+
"0"
877+
878+
julia> LaTeXOutputOfHomalgRingElement(ZZ(-3))
879+
"-3"
880+
881+
julia> LaTeXOutputOfHomalgRingElement(QQ(1, 3))
882+
"\\\\frac{1}{3}"
883+
884+
julia> LaTeXOutputOfHomalgRingElement(QQ(-1, 4))
885+
"-\\\\frac{1}{4}"
886+
```
887+
"""
888+
function LaTeXOutputOfHomalgRingElement(x::Nemo.ZZRingElem)::String
889+
return string(x)
890+
end
891+
892+
function LaTeXOutputOfHomalgRingElement(x::Nemo.QQFieldElem)::String
893+
d = Nemo.denominator(x)
894+
if Nemo.isone(d)
895+
return string(Nemo.numerator(x))
896+
end
897+
n = Nemo.numerator(x)
898+
if n < 0
899+
return "-\\frac{$(abs(n))}{$(d)}"
900+
end
901+
return "\\frac{$(n)}{$(d)}"
902+
end
903+
904+
"""
905+
LaTeXOutputOfHomalgRing(R)
906+
907+
Return a LaTeX string for the ring R.
908+
909+
```jldoctest
910+
julia> LaTeXOutputOfHomalgRing(HomalgRingOfIntegers())
911+
"\\\\mathbb{Z}"
912+
913+
julia> LaTeXOutputOfHomalgRing(HomalgFieldOfRationals())
914+
"\\\\mathbb{Q}"
915+
```
916+
"""
917+
function LaTeXOutputOfHomalgRing(::Nemo.ZZRing)::String
918+
return "\\mathbb{Z}"
919+
end
920+
921+
function LaTeXOutputOfHomalgRing(::Nemo.QQField)::String
922+
return "\\mathbb{Q}"
923+
end
924+
925+
"""
926+
LaTeXOutputOfHomalgMatrix(mat)
927+
928+
Return a LaTeX string representing the matrix mat as a \\left( \\begin{array} ... \\end{array} \\right) expression.
929+
930+
```jldoctest
931+
julia> mat = HomalgMatrix([2], 1, 1, QQ)
932+
[2]
933+
934+
julia> LaTeXOutputOfHomalgMatrix(mat)
935+
"\\\\left( \\\\begin{array}{r}\\n 2 \\n\\\\end{array} \\\\right)"
936+
937+
julia> mat = HomalgMatrix([[2, QQ(1,3)]], 1, 2, QQ)
938+
[2 1//3]
939+
940+
julia> LaTeXOutputOfHomalgMatrix(mat)
941+
"\\\\left( \\\\begin{array}{rr}\\n 2 & \\\\frac{1}{3} \\n\\\\end{array} \\\\right)"
942+
```
943+
"""
944+
function LaTeXOutputOfHomalgMatrix(mat)::String
945+
r = NumberRows(mat)
946+
c = NumberColumns(mat)
947+
col_spec = repeat("r", c)
948+
rows_str = join(
949+
[ join([_latex_entry(mat[i, j]) for j in 1:c], " & ") for i in 1:r ],
950+
" \\\\\n "
951+
)
952+
return "\\left( \\begin{array}{$(col_spec)}\n $(rows_str) \n\\end{array} \\right)"
953+
end
954+
851955
export HomalgRing, NumberRows, NumberColumns, TransposedMatrix, ConvertMatrixToRow, ConvertMatrixToColumn,
852956
RowReducedEchelonForm, BasisOfRows, BasisOfColumns, ZeroRows, ZeroColumns, FirstZeroRow, FirstZeroColumn,
853957
SyzygiesOfRows, SyzygiesOfColumns, RowRankOfMatrix, ColumnRankOfMatrix, StringDisplay,
958+
LaTeXOutputOfHomalgMatrix, LaTeXOutputOfHomalgRing, LaTeXOutputOfHomalgRingElement,
854959
ReducedSyzygiesOfRows, ReducedSyzygiesOfColumns
855960

856961
## Operations of homalg matrices

test/latex.jl

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
@testset "LaTeXOutputOfHomalgRingElement" begin
2+
@test LaTeXOutputOfHomalgRingElement(ZZ(0)) == "0"
3+
@test LaTeXOutputOfHomalgRingElement(ZZ(-3)) == "-3"
4+
@test LaTeXOutputOfHomalgRingElement(ZZ(42)) == "42"
5+
@test LaTeXOutputOfHomalgRingElement(QQ(0)) == "0"
6+
@test LaTeXOutputOfHomalgRingElement(QQ(2)) == "2"
7+
@test LaTeXOutputOfHomalgRingElement(QQ(1,3)) == "\\frac{1}{3}"
8+
@test LaTeXOutputOfHomalgRingElement(QQ(-1,4)) == "-\\frac{1}{4}"
9+
end
10+
11+
@testset "LaTeXOutputOfHomalgRing" begin
12+
@test LaTeXOutputOfHomalgRing(ZZ) == "\\mathbb{Z}"
13+
@test LaTeXOutputOfHomalgRing(QQ) == "\\mathbb{Q}"
14+
end
15+
16+
@testset "LaTeXOutputOfHomalgMatrix" begin
17+
# integer matrix: zero becomes \cdot
18+
mat = HomalgMatrix([0, 1, 2, 0], 2, 2, ZZ)
19+
@test LaTeXOutputOfHomalgMatrix(mat) == "\\left( \\begin{array}{rr}\n \\cdot & 1 \\\\\n 2 & \\cdot \n\\end{array} \\right)"
20+
21+
# rational matrix: fraction and zero
22+
mat = HomalgMatrix([QQ(0), QQ(1, 3)], 1, 2, QQ)
23+
@test LaTeXOutputOfHomalgMatrix(mat) == "\\left( \\begin{array}{rr}\n \\cdot & \\frac{1}{3} \n\\end{array} \\right)"
24+
25+
# rational matrix: negative fraction
26+
mat = HomalgMatrix([QQ(-1, 4)], 1, 1, QQ)
27+
@test LaTeXOutputOfHomalgMatrix(mat) == "\\left( \\begin{array}{r}\n -\\frac{1}{4} \n\\end{array} \\right)"
28+
29+
# identity matrix
30+
mat = HomalgIdentityMatrix(2, ZZ)
31+
@test LaTeXOutputOfHomalgMatrix(mat) == "\\left( \\begin{array}{rr}\n 1 & \\cdot \\\\\n \\cdot & 1 \n\\end{array} \\right)"
32+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ include("constructors.jl")
99
include("properties.jl")
1010
include("attributes.jl")
1111
include("operations.jl")
12+
include("latex.jl")
1213
include("testmanual.jl")
1314
include("singular-ext-test.jl")

0 commit comments

Comments
 (0)