From 41678ac4bc55f85a04da7074cdf93f7849ef6406 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 13 Dec 2023 16:39:47 +0100 Subject: [PATCH 01/18] spare_row and SRow accept NCRing instead of Ring (for modules over NCRing) --- src/HeckeTypes.jl | 10 +++++----- src/Sparse/Row.jl | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/HeckeTypes.jl b/src/HeckeTypes.jl index 25a76f510b..c24364e33c 100644 --- a/src/HeckeTypes.jl +++ b/src/HeckeTypes.jl @@ -315,13 +315,13 @@ mutable struct SRow{T, S} # S <: AbstractVector{T} values::S pos::Vector{Int} - function SRow(R::Ring) + function SRow(R::NCRing) @assert R != ZZ r = new{elem_type(R), Vector{elem_type(R)}}(R, Vector{elem_type(R)}(), Vector{Int}()) return r end - function SRow(R::Ring, p::Vector{Int64}, S::AbstractVector; check::Bool = true) + function SRow(R::NCRing, p::Vector{Int64}, S::AbstractVector; check::Bool = true) if check && any(iszero, S) p = copy(p) S = deepcopy(S) @@ -339,7 +339,7 @@ mutable struct SRow{T, S} # S <: AbstractVector{T} return r end - function SRow(R::Ring, A::Vector{Tuple{Int, T}}) where T + function SRow(R::NCRing, A::Vector{Tuple{Int, T}}) where T r = SRow(R) for (i, v) = A if !iszero(v) @@ -351,7 +351,7 @@ mutable struct SRow{T, S} # S <: AbstractVector{T} return r end - function SRow(R::Ring, A::Vector{Tuple{Int, Int}}) + function SRow(R::NCRing, A::Vector{Tuple{Int, Int}}) r = SRow(R) for (i, v) = A if !iszero(v) @@ -371,7 +371,7 @@ mutable struct SRow{T, S} # S <: AbstractVector{T} return r end - function SRow{T}(R::Ring, pos::Vector{Int}, val::Vector{T}) where {T} + function SRow{T}(R::NCRing, pos::Vector{Int}, val::Vector{T}) where {T} length(pos) == length(val) || error("Arrays must have same length") r = SRow(R) for i=1:length(pos) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index 8b12dad349..b52cd05422 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -40,7 +40,7 @@ end Constructs an empty row with base ring $R$. """ -function sparse_row(R::Ring) +function sparse_row(R::NCRing) return SRow(R) end @@ -51,7 +51,7 @@ const _sort = sort Constructs the sparse row $(a_i)_i$ with $a_{i_j} = x_j$, where $J = (i_j, x_j)_j$. The elements $x_i$ must belong to the ring $R$. """ -function sparse_row(R::Ring, A::Vector{Tuple{Int, T}}; sort::Bool = true) where T +function sparse_row(R::NCRing, A::Vector{Tuple{Int, T}}; sort::Bool = true) where T if sort A = _sort(A, lt=(a,b) -> isless(a[1], b[1])) end @@ -64,7 +64,7 @@ end Constructs the sparse row $(a_i)_i$ over $R$ with $a_{i_j} = x_j$, where $J = (i_j, x_j)_j$. """ -function sparse_row(R::Ring, A::Vector{Tuple{Int, Int}}; sort::Bool = true) +function sparse_row(R::NCRing, A::Vector{Tuple{Int, Int}}; sort::Bool = true) if sort A = _sort(A, lt=(a,b)->isless(a[1], b[1])) end @@ -84,12 +84,12 @@ function swap!(A::SRow, B::SRow) end @doc raw""" - sparse_row(R::Ring, J::Vector{Int}, V::Vector{T}) -> SRow{T} + sparse_row(R::NCRing, J::Vector{Int}, V::Vector{T}) -> SRow{T} Constructs the sparse row $(a_i)_i$ over $R$ with $a_{i_j} = x_j$, where $J = (i_j)_j$ and $V = (x_j)_j$. """ -function sparse_row(R::Ring, pos::Vector{Int}, val::AbstractVector{T}; sort::Bool = true) where T +function sparse_row(R::NCRing, pos::Vector{Int}, val::AbstractVector{T}; sort::Bool = true) where T if sort p = sortperm(pos) pos = pos[p] @@ -266,7 +266,7 @@ end Create a new sparse row by coercing all elements into the ring $R$. """ -function change_base_ring(R::S, A::SRow{T}) where {T <: RingElem, S <: Ring} +function change_base_ring(R::S, A::SRow{T}) where {T <: NCRingElem, S <: NCRing} z = sparse_row(R) for (i, v) in A nv = R(v) @@ -293,7 +293,7 @@ end Given a sparse row $(a_i)_{i}$ and an index $j$ return $a_j$. """ -function Base.getindex(A::SRow{T}, i::Int) where {T <: RingElem} +function Base.getindex(A::SRow{T}, i::Int) where {T <: NCRingElem} i < 1 && error("Index must be positive") p = findfirst(isequal(i), A.pos) if p === nothing From 9abef0c2aac42edbcf14a2f593f3ed633d2876f8 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 20 Dec 2023 17:57:15 +0100 Subject: [PATCH 02/18] left and right functionality for SRow over NCRing --- src/Sparse/Row.jl | 111 ++++++++++++++++++++++++++++++++++++++++++--- test/Sparse/Row.jl | 10 ++++ 2 files changed, 115 insertions(+), 6 deletions(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index b52cd05422..bf7fe20823 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -343,7 +343,7 @@ Base.IteratorSize(::SRow{T}) where T = Base.HasLength() @doc raw""" dot(A::SRow, B::SRow) -> RingElem -Returns the dot product of $A$ and $B$. +Returns the dot product of $A$ and $B$. Note the order matters in non-commutative case. """ function dot(A::SRow{T}, B::SRow{T}) where T @assert length(A) != 0 @@ -357,7 +357,7 @@ function dot(A::SRow{T}, B::SRow{T}) where T return v end if B.pos[b] == A.pos[a] - v += B.values[b] * A.values[a] + v += A.values[a] * B.values[b] end end return v @@ -419,8 +419,28 @@ end # Inplace scaling # ################################################################################ +@doc raw""" + scale_row!(a::SRow, b::NCRingElem) -> SRow +Returns the (left) product of $b \times a$. +For Rows, the standard multiplication is from the left. +""" function scale_row!(a::SRow{T}, b::T) where T + @assert !iszero(b) + if isone(b) + return + end + for i=1:length(a.pos) + a.values[i] = b*a.values[i] + end +end + +@doc raw""" + scale_row_right!(a::SRow, b::NCRingElem) -> SRow + +Returns the (right) product of $a \times b$. +""" +function scale_row_right!(a::SRow{T}, b::T) where T @assert !iszero(b) if isone(b) return @@ -430,6 +450,10 @@ function scale_row!(a::SRow{T}, b::T) where T end end +function scale_row_left!(a::SRow{T}, b::T) where T + return scale_row!(a,b) +end + ################################################################################ # # Addition @@ -515,6 +539,7 @@ function *(A::SRow, b) return A*base_ring(A)(b) end +#left and right div not implimented function div(A::SRow{T}, b::T) where T B = sparse_row(base_ring(A)) if iszero(b) @@ -537,13 +562,18 @@ function div(A::SRow{T}, b::Integer) where T return div(A, base_ring(A)(b)) end +@doc raw""" + divexact(A::SRow, b::NCRingElem) -> SRow + +Returns the left divexact $A/b$ +""" function divexact(A::SRow{T}, b::T) where T B = sparse_row(base_ring(A)) if iszero(b) return error("Division by zero") end for (p,v) = A - nv = divexact(v, b) + nv = divexact_left(v, b) @assert !iszero(nv) push!(B.pos, p) push!(B.values, nv) @@ -555,7 +585,33 @@ function divexact(A::SRow{T}, b::Integer) where T if length(A.values) == 0 return deepcopy(A) end - return divexact(A, base_ring(A)(b)) + return divexact_left(A, base_ring(A)(b)) +end + +@doc raw""" + divexact_right(A::SRow, b::NCRingElem) -> SRow + +Returns the left divexact $A/b$ +""" +function divexact_right(A::SRow{T}, b::T) where T + B = sparse_row(base_ring(A)) + if iszero(b) + return error("Division by zero") + end + for (p,v) = A + nv = divexact_right(v, b) + @assert !iszero(nv) + push!(B.pos, p) + push!(B.values, nv) + end + return B +end + +function divexact_right(A::SRow{T}, b::Integer) where T + if length(A.values) == 0 + return deepcopy(A) + end + return divexact_right(A, base_ring(A)(b)) end ################################################################################ @@ -582,11 +638,12 @@ end Returns the row $c A + B$. """ add_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_scaled_row!(a, deepcopy(b), c) +add_left_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_scaled_row!(a, deepcopy(b), c) @doc raw""" add_scaled_row!(A::SRow{T}, B::SRow{T}, c::T) -> SRow{T} -Returns the row $c A + B$ by changing $B$ in place. +Returns the left scaled row $c A$ to $B$ by changing $B$ in place. """ function add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T @assert a !== b @@ -622,7 +679,49 @@ function add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T return b end -add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T, tmp::SRow{T}) where T = add_scaled_row!(a, b, c) +add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T, tmp::SRow{T}) where T = add_scaled_row!(a, b, c) + +add_right_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_right_scaled_row!(a, deepcopy(b), c) + +@doc raw""" + add_right_scaled_row!(A::SRow{T}, B::SRow{T}, c::T) -> SRow{T} + +Returns the right scaled row $c A$ to $B$ by changing $B$ in place. +""" + +function add_right_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T + @assert a !== b + i = 1 + j = 1 + t = base_ring(a)() + while i <= length(a) && j <= length(b) + if a.pos[i] < b.pos[j] + insert!(b.pos, j, a.pos[i]) + insert!(b.values, j, a.values[i]*c) + i += 1 + j += 1 + elseif a.pos[i] > b.pos[j] + j += 1 + else + t = mul!(t, a.values[i], c) + b.values[j] = addeq!(b.values[j], t) + + if iszero(b.values[j]) + deleteat!(b.values, j) + deleteat!(b.pos, j) + else + j += 1 + end + i += 1 + end + end + while i <= length(a) + push!(b.pos, a.pos[i]) + push!(b.values, a.values[i]*c) + i += 1 + end + return b +end ################################################################################ # diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index 3a0cc489d4..abe900eae3 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -163,4 +163,14 @@ @test dense_row(A, 3) == matrix(FlintZZ, 1, 3, [-5, 0, 2]) @test dense_row(A, 6) == matrix(FlintZZ, 1, 6, [-5, 0, 2, -10, 1, 0]) @test sparse_row(dense_row(A, 6)) == A + + #SRow{NCRingElem} + #uses exterior algebras from Oscar, not available in Hecke + E,e = exterior_algebra(QQ,3) + A = sparse_row(E, [1,2,3], [e[1], e[2], e[3]]) + b = sparse_row(E, [1,2,3], [e[1], e[2], e[3]]) + B = sparse_row(E, [1,2,3], [e[2], e[3], e[1]]) + @test dot(A,B) != dot(B,A) + @test dot(A,b) == dot(b,A) == E(0) + @test A*e[1] != e[1]*A end From 302c3bb22901eaf14d876fbf41f6ea29d2ef1087 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 20 Dec 2023 18:14:12 +0100 Subject: [PATCH 03/18] functionality and tests for scale_row :wq yes --- src/Sparse/Row.jl | 6 ++++-- test/Sparse/Row.jl | 3 +++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index bf7fe20823..7b8382b236 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -428,11 +428,12 @@ For Rows, the standard multiplication is from the left. function scale_row!(a::SRow{T}, b::T) where T @assert !iszero(b) if isone(b) - return + return a end for i=1:length(a.pos) a.values[i] = b*a.values[i] end + return a end @doc raw""" @@ -443,11 +444,12 @@ Returns the (right) product of $a \times b$. function scale_row_right!(a::SRow{T}, b::T) where T @assert !iszero(b) if isone(b) - return + return a end for i=1:length(a.pos) a.values[i] *= b end + return a end function scale_row_left!(a::SRow{T}, b::T) where T diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index abe900eae3..acd1e49bde 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -173,4 +173,7 @@ @test dot(A,B) != dot(B,A) @test dot(A,b) == dot(b,A) == E(0) @test A*e[1] != e[1]*A + @test scale_row!(A, e[1]) != scale_row_right!(b, e[1]) + C = add_scaled_row(A,b,E(1)) + @test A + C == A end From 950fefad638cf74054ac9a73b4b7f91073445901 Mon Sep 17 00:00:00 2001 From: Lax202 <115473549+Lax202@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:52:30 +0100 Subject: [PATCH 04/18] Update src/Sparse/Row.jl Co-authored-by: Max Horn --- src/Sparse/Row.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index 7b8382b236..a6a8792839 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -437,7 +437,7 @@ function scale_row!(a::SRow{T}, b::T) where T end @doc raw""" - scale_row_right!(a::SRow, b::NCRingElem) -> SRow + scale_row_right!(a::SRow, b::NCRingElem) -> SRow Returns the (right) product of $a \times b$. """ From 55e6b4ae0be67f66644b5c7a9e3f193e32cca47d Mon Sep 17 00:00:00 2001 From: Lax202 <115473549+Lax202@users.noreply.github.com> Date: Thu, 4 Jan 2024 11:52:44 +0100 Subject: [PATCH 05/18] Update src/Sparse/Row.jl Co-authored-by: Johannes Schmitt --- src/Sparse/Row.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index a6a8792839..e3ca57c34e 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -593,7 +593,7 @@ end @doc raw""" divexact_right(A::SRow, b::NCRingElem) -> SRow -Returns the left divexact $A/b$ +Returns the right divexact $A/b$ """ function divexact_right(A::SRow{T}, b::T) where T B = sparse_row(base_ring(A)) From 8676d2ad40c765e900a5593eccef3463080230c3 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 24 Jan 2024 15:17:38 +0100 Subject: [PATCH 06/18] minor documentation modification --- src/Sparse/Row.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index 7b8382b236..826367e3a6 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -645,7 +645,7 @@ add_left_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_scaled_row!(a, @doc raw""" add_scaled_row!(A::SRow{T}, B::SRow{T}, c::T) -> SRow{T} -Returns the left scaled row $c A$ to $B$ by changing $B$ in place. +Adds the left scaled row $c A$ to $B$ by changing $B$ in place. Returns the new $B$. """ function add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T @assert a !== b From 22bee558f2051e23ab8b01188ea2f0a505d27982 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 24 Jan 2024 15:57:43 +0100 Subject: [PATCH 07/18] added export functions --- src/Sparse/Row.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index 4aa9b34637..2bd6098905 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -1,6 +1,6 @@ import Base.Vector -export sparse_row, dot, scale_row!, add_scaled_row, permute_row, dense_row +export sparse_row, dot, scale_row!, add_scaled_row, permute_row, dense_row, scale_row_right!, add_right_scaled_row ################################################################################ # @@ -645,7 +645,7 @@ add_left_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_scaled_row!(a, @doc raw""" add_scaled_row!(A::SRow{T}, B::SRow{T}, c::T) -> SRow{T} -Adds the left scaled row $c A$ to $B$ by changing $B$ in place. Returns the new $B$. +Adds the left scaled row $c A$ to $B$. """ function add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T @assert a !== b From 719c07ad1705aa6e662c319ac5843e2e64a5f988 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 24 Jan 2024 15:58:30 +0100 Subject: [PATCH 08/18] tests for SRow{NCRingElem} --- test/Sparse/Row.jl | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index acd1e49bde..0b9cbba668 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -165,15 +165,15 @@ @test sparse_row(dense_row(A, 6)) == A #SRow{NCRingElem} - #uses exterior algebras from Oscar, not available in Hecke - E,e = exterior_algebra(QQ,3) - A = sparse_row(E, [1,2,3], [e[1], e[2], e[3]]) - b = sparse_row(E, [1,2,3], [e[1], e[2], e[3]]) - B = sparse_row(E, [1,2,3], [e[2], e[3], e[1]]) + R = MatrixAlgebra(QQ,2) + a = R([1 2; 3 4]) + b = R([3 4; 5 6]) + i = R([1 0; 0 1]) + A = sparse_row(R,[1],[a]) + B = sparse_row(R,[1],[b]) @test dot(A,B) != dot(B,A) - @test dot(A,b) == dot(b,A) == E(0) - @test A*e[1] != e[1]*A - @test scale_row!(A, e[1]) != scale_row_right!(b, e[1]) - C = add_scaled_row(A,b,E(1)) - @test A + C == A + @test A*i == A == i*A + @test scale_row!(A,b) != scale_row_right!(A,b) + C = add_scaled_row(A,B,i) + @test C == A+B end From 25e43951ae009e4c72dc8675af766426a02cafcf Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 5 Jun 2024 12:54:29 +0200 Subject: [PATCH 09/18] minor changes from PR comments --- src/Sparse/Row.jl | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index b1c413c899..366f5ad590 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -421,7 +421,7 @@ end scale_row!(a::SRow, b::NCRingElem) -> SRow Returns the (left) product of $b \times a$. -For Rows, the standard multiplication is from the left. +For rows, the standard multiplication is from the left. """ function scale_row!(a::SRow{T}, b::T) where T @assert !iszero(b) @@ -539,7 +539,7 @@ function *(A::SRow, b) return A*base_ring(A)(b) end -#left and right div not implimented +#left and right div not implemented function div(A::SRow{T}, b::T) where T B = sparse_row(base_ring(A)) if iszero(b) @@ -563,11 +563,13 @@ function div(A::SRow{T}, b::Integer) where T end @doc raw""" - divexact(A::SRow, b::NCRingElem; check::Bool = true) -> SRow + divexact(A::SRow, b::RingElem; check::Bool = true) -> SRow -Returns the left divexact $A/b$ +Return $C$ such that $a = b \cdot C$. Implicitly calling divexact_left(A,b;check) """ -function divexact(A::SRow{T}, b::T; check::Bool=true) where T +divexact(A::SRow{T}, b::T; check::Bool=true) where T <: RingElem = divexact_left(A, b; check) + +function divexact_left(A::SRow{T}, b::T; check::Bool=true) where T <: NCRingElem B = sparse_row(base_ring(A)) if iszero(b) return error("Division by zero") @@ -591,7 +593,7 @@ end @doc raw""" divexact_right(A::SRow, b::NCRingElem; check::Bool = true) -> SRow -Returns the right divexact $A/b$ +Return $C$ such that $A = C \cdot b. """ function divexact_right(A::SRow{T}, b::T; check::Bool=true) where T B = sparse_row(base_ring(A)) @@ -686,7 +688,7 @@ add_right_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_right_scaled_ @doc raw""" add_right_scaled_row!(A::SRow{T}, B::SRow{T}, c::T) -> SRow{T} -Returns the right scaled row $c A$ to $B$ by changing $B$ in place. +Return the right scaled row $c A$ to $B$ by changing $B$ in place. """ function add_right_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T From 376cbdd799564373b364cbbae48db7e4ab91651d Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 5 Jun 2024 13:01:28 +0200 Subject: [PATCH 10/18] fixed scale row test --- test/Sparse/Row.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index 0b9cbba668..f358122511 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -170,10 +170,11 @@ b = R([3 4; 5 6]) i = R([1 0; 0 1]) A = sparse_row(R,[1],[a]) + AA = sparse_row(R,[1],[a]) B = sparse_row(R,[1],[b]) @test dot(A,B) != dot(B,A) @test A*i == A == i*A - @test scale_row!(A,b) != scale_row_right!(A,b) + @test !(scale_row!(A,b) == scale_row_right!(AA,b)) C = add_scaled_row(A,B,i) @test C == A+B end From 4228cfe7c107c0602d57c8f417e6fdb79a8191e9 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 5 Jun 2024 14:34:01 +0200 Subject: [PATCH 11/18] resolving conflict --- src/Sparse/Row.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index b1c413c899..86735190e1 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -50,8 +50,8 @@ Constructs the sparse row $(a_i)_i$ with $a_{i_j} = x_j$, where $J = (i_j, x_j)_ The elements $x_i$ must belong to the ring $R$. """ function sparse_row(R::NCRing, A::Vector{Tuple{Int, T}}; sort::Bool = true) where T - if sort - A = _sort(A, lt=(a,b) -> isless(a[1], b[1])) + if sort && length(A) > 1 + A = Base.sort(A, lt=(a,b) -> isless(a[1], b[1])) end return SRow(R, A) end @@ -63,8 +63,8 @@ Constructs the sparse row $(a_i)_i$ over $R$ with $a_{i_j} = x_j$, where $J = (i_j, x_j)_j$. """ function sparse_row(R::NCRing, A::Vector{Tuple{Int, Int}}; sort::Bool = true) - if sort - A = _sort(A, lt=(a,b)->isless(a[1], b[1])) + if sort && length(A) > 1 + A = Base.sort(A, lt=(a,b) -> isless(a[1], b[1])) end return SRow(R, A) end @@ -88,7 +88,7 @@ Constructs the sparse row $(a_i)_i$ over $R$ with $a_{i_j} = x_j$, where $J = (i_j)_j$ and $V = (x_j)_j$. """ function sparse_row(R::NCRing, pos::Vector{Int}, val::AbstractVector{T}; sort::Bool = true) where T - if sort + if sort && length(pos) > 1 p = sortperm(pos) pos = pos[p] val = val[p] From def37dae7003a22fa81f0f0c3ba5d282cbb848f1 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 5 Jun 2024 23:18:01 +0200 Subject: [PATCH 12/18] small fix in sparse row test --- test/Sparse/Row.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index f358122511..caacb097d5 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -165,7 +165,7 @@ @test sparse_row(dense_row(A, 6)) == A #SRow{NCRingElem} - R = MatrixAlgebra(QQ,2) + R = matrix_algebra(QQ,2) a = R([1 2; 3 4]) b = R([3 4; 5 6]) i = R([1 0; 0 1]) From 57a12f4560f096ff62721d2bb404568965bac938 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Mon, 10 Jun 2024 15:02:54 +0200 Subject: [PATCH 13/18] fixes to make sparse row over NCRing work --- src/HeckeTypes.jl | 6 +++--- src/Sparse/Row.jl | 15 +++++++++++---- test/Sparse/Row.jl | 6 +++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/HeckeTypes.jl b/src/HeckeTypes.jl index 8d8764b3af..0373e1daa5 100644 --- a/src/HeckeTypes.jl +++ b/src/HeckeTypes.jl @@ -390,9 +390,9 @@ end # helper function used by SRow construct and also by the default # methods for `sparse_matrix_type` and `sparse_row_type`. -sparse_inner_type(::T) where {T <: Union{Ring, RingElem}} = sparse_inner_type(T) -sparse_inner_type(::Type{T}) where {T <: Ring} = sparse_inner_type(elem_type(T)) -sparse_inner_type(::Type{T}) where {T <: RingElem} = Vector{T} +sparse_inner_type(::T) where {T <: Union{NCRing, NCRingElem}} = sparse_inner_type(T) +sparse_inner_type(::Type{T}) where {T <: NCRing} = sparse_inner_type(elem_type(T)) +sparse_inner_type(::Type{T}) where {T <: NCRingElem} = Vector{T} ################################################################################ # diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index 1a8351202b..91e4d85b2c 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -51,9 +51,9 @@ julia> sparse_row_type(typeof(zero(QQ))) == typeof(x) true ``` """ -sparse_row_type(::T) where {T <: Union{Ring, RingElem}} = sparse_row_type(T) -sparse_row_type(::Type{T}) where {T <: Ring} = sparse_row_type(elem_type(T)) -sparse_row_type(::Type{T}) where {T <: RingElem} = SRow{T, sparse_inner_type(T)} +sparse_row_type(::T) where {T <: Union{NCRing, NCRingElem}} = sparse_row_type(T) +sparse_row_type(::Type{T}) where {T <: NCRing} = sparse_row_type(elem_type(T)) +sparse_row_type(::Type{T}) where {T <: NCRingElem} = SRow{T, sparse_inner_type(T)} ==(x::SRow{T}, y::SRow{T}) where {T} = (x.pos == y.pos) && (x.values == y.values) @@ -461,8 +461,15 @@ function scale_row!(a::SRow{T}, b::T) where T if isone(b) return a end - for i=1:length(a.pos) + i = 1 + while i <= length(a) a.values[i] = b*a.values[i] + if iszero(a.values[i]) + deleteat!(a.values, i) + deleteat!(a.pos, i) + else + i += 1 + end end return a end diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index bafa645e37..157b38af14 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -176,9 +176,9 @@ #SRow{NCRingElem} R = matrix_algebra(QQ,2) - a = R([1 2; 3 4]) - b = R([3 4; 5 6]) - i = R([1 0; 0 1]) + a = R(matrix(QQ,[1 2; 3 4])) + b = R(matrix(QQ,[3 4; 5 6])) + i = R(1) A = sparse_row(R,[1],[a]) AA = sparse_row(R,[1],[a]) B = sparse_row(R,[1],[b]) From bfc8d0971bf4956a7e55e89af527f8bf0aa78fb9 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Mon, 10 Jun 2024 15:10:41 +0200 Subject: [PATCH 14/18] minor changes from PR --- src/Sparse/Row.jl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index 91e4d85b2c..ac5df47178 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -93,7 +93,6 @@ end Constructs the sparse row $(a_i)_i$ over $R$ with $a_{i_j} = x_j$, where $J = (i_j, x_j)_j$. """ - function sparse_row(R::NCRing, A::Vector{Tuple{Int, Int}}; sort::Bool = true) if sort && length(A) > 1 A = Base.sort(A, lt=(a,b) -> isless(a[1], b[1])) @@ -119,7 +118,6 @@ end Constructs the sparse row $(a_i)_i$ over $R$ with $a_{i_j} = x_j$, where $J = (i_j)_j$ and $V = (x_j)_j$. """ - function sparse_row(R::NCRing, pos::Vector{Int}, val::AbstractVector{T}; sort::Bool = true) where T if sort && length(pos) > 1 p = sortperm(pos) @@ -453,7 +451,7 @@ end @doc raw""" scale_row!(a::SRow, b::NCRingElem) -> SRow -Returns the (left) product of $b \times a$. +Returns the (left) product of $b \times a$ and reassigns the value of $a$ to this product. For rows, the standard multiplication is from the left. """ function scale_row!(a::SRow{T}, b::T) where T @@ -477,7 +475,7 @@ end @doc raw""" scale_row_right!(a::SRow, b::NCRingElem) -> SRow -Returns the (right) product of $a \times b$. +Returns the (right) product of $a \times b$ and modifies $a$ to this product. """ function scale_row_right!(a::SRow{T}, b::T) where T @assert !iszero(b) @@ -612,7 +610,7 @@ end @doc raw""" divexact(A::SRow, b::RingElem; check::Bool = true) -> SRow -Return $C$ such that $a = b \cdot C$. Implicitly calling divexact_left(A,b;check) +Return $C$ such that $a = b \cdot C$. Calls the function `divexact_left(A,b;check)` """ divexact(A::SRow{T}, b::T; check::Bool=true) where T <: RingElem = divexact_left(A, b; check) From 30ef82b43357034d627fcd75dbbac5571408e8de Mon Sep 17 00:00:00 2001 From: Lax202 Date: Wed, 19 Jun 2024 15:44:02 +0200 Subject: [PATCH 15/18] test for add_scaled_row avoiding MatAlgElem --- test/Sparse/Row.jl | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index 157b38af14..0febd16967 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -174,7 +174,7 @@ @test dense_row(A, 6) == matrix(FlintZZ, 1, 6, [-5, 0, 2, -10, 1, 0]) @test sparse_row(dense_row(A, 6)) == A - #SRow{NCRingElem} + SRow{NCRingElem} R = matrix_algebra(QQ,2) a = R(matrix(QQ,[1 2; 3 4])) b = R(matrix(QQ,[3 4; 5 6])) @@ -185,6 +185,12 @@ @test dot(A,B) != dot(B,A) @test A*i == A == i*A @test !(scale_row!(A,b) == scale_row_right!(AA,b)) - C = add_scaled_row(A,B,i) + #C = add_scaled_row(A,B,i) + #@test C == A+B + + F, (x,y) = free_associative_algebra(QQ,[:x, :y]) + A = sparse_row(F,[1],[x]) + B = sparse_row(F,[1],[y]) + C = add_scaled_row(A,B,F(1)) @test C == A+B end From b66ba3ded0dfd3da2699377252efbeae0564a08e Mon Sep 17 00:00:00 2001 From: Lax202 Date: Mon, 22 Jul 2024 11:54:21 +0200 Subject: [PATCH 16/18] changed docs for sparse_row --- docs/src/manual/misc/sparse.md | 6 +++--- docs/src/sparse/intro.md | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/src/manual/misc/sparse.md b/docs/src/manual/misc/sparse.md index a485107f77..0b14d3d701 100644 --- a/docs/src/manual/misc/sparse.md +++ b/docs/src/manual/misc/sparse.md @@ -28,9 +28,9 @@ In particular any two sparse rows over the same base ring can be added. ### Creation ```@docs -sparse_row(::ZZRing, ::Vector{Tuple{Int, ZZRingElem}}) -sparse_row(::ZZRing, ::Vector{Tuple{Int, Int}}) -sparse_row(::ZZRing, ::Vector{Int}, ::Vector{ZZRingElem}) +sparse_row(::NCRing, ::Vector{Tuple{Int, NCRingElem}}) +sparse_row(::NCRing, ::Vector{Tuple{Int, Int}}) +sparse_row(::NCRing, ::Vector{Int}, ::Vector{NCRingElem}) ``` ### Basic operations diff --git a/docs/src/sparse/intro.md b/docs/src/sparse/intro.md index a03bb3d621..2e896dd917 100644 --- a/docs/src/sparse/intro.md +++ b/docs/src/sparse/intro.md @@ -28,9 +28,9 @@ In particular any two sparse rows over the same base ring can be added. ### Creation ```@docs; canonical=false -sparse_row(::ZZRing, ::Vector{Tuple{Int, ZZRingElem}}) -sparse_row(::ZZRing, ::Vector{Tuple{Int, Int}}) -sparse_row(::ZZRing, ::Vector{Int}, ::Vector{ZZRingElem}) +sparse_row(::NCRing, ::Vector{Tuple{Int, NCRingElem}}) +sparse_row(::NCRing, ::Vector{Tuple{Int, Int}}) +sparse_row(::NCRing, ::Vector{Int}, ::Vector{NCRingElem}) ``` ### Basic operations From f6d359e30b6993255d697df6b2dbe497a3915aa8 Mon Sep 17 00:00:00 2001 From: Lax202 Date: Mon, 22 Jul 2024 14:36:34 +0200 Subject: [PATCH 17/18] fixed documentation for sparse_row --- docs/src/manual/misc/sparse.md | 4 ++-- docs/src/sparse/intro.md | 4 ++-- src/Sparse/Row.jl | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/src/manual/misc/sparse.md b/docs/src/manual/misc/sparse.md index 0b14d3d701..ba5b3685a9 100644 --- a/docs/src/manual/misc/sparse.md +++ b/docs/src/manual/misc/sparse.md @@ -28,9 +28,9 @@ In particular any two sparse rows over the same base ring can be added. ### Creation ```@docs -sparse_row(::NCRing, ::Vector{Tuple{Int, NCRingElem}}) +sparse_row(::NCRing, ::Vector{Tuple{Int, T}}) where T sparse_row(::NCRing, ::Vector{Tuple{Int, Int}}) -sparse_row(::NCRing, ::Vector{Int}, ::Vector{NCRingElem}) +sparse_row(::NCRing, ::Vector{Int}, ::Vector{T}) where T ``` ### Basic operations diff --git a/docs/src/sparse/intro.md b/docs/src/sparse/intro.md index 2e896dd917..970b3aa714 100644 --- a/docs/src/sparse/intro.md +++ b/docs/src/sparse/intro.md @@ -28,9 +28,9 @@ In particular any two sparse rows over the same base ring can be added. ### Creation ```@docs; canonical=false -sparse_row(::NCRing, ::Vector{Tuple{Int, NCRingElem}}) +sparse_row(::NCRing, ::Vector{Tuple{Int, T}}) where T sparse_row(::NCRing, ::Vector{Tuple{Int, Int}}) -sparse_row(::NCRing, ::Vector{Int}, ::Vector{NCRingElem}) +sparse_row(::NCRing, ::Vector{Int}, ::Vector{T}) where T ``` ### Basic operations diff --git a/src/Sparse/Row.jl b/src/Sparse/Row.jl index ac5df47178..17f0fc4aa3 100644 --- a/src/Sparse/Row.jl +++ b/src/Sparse/Row.jl @@ -79,7 +79,6 @@ end Constructs the sparse row $(a_i)_i$ with $a_{i_j} = x_j$, where $J = (i_j, x_j)_j$. The elements $x_i$ must belong to the ring $R$. """ - function sparse_row(R::NCRing, A::Vector{Tuple{Int, T}}; sort::Bool = true) where T if sort && length(A) > 1 A = Base.sort(A, lt=(a,b) -> isless(a[1], b[1])) From 2e90d2c0327f835044861642240277608d4cbc3b Mon Sep 17 00:00:00 2001 From: Lax202 Date: Mon, 22 Jul 2024 14:39:26 +0200 Subject: [PATCH 18/18] fixed test --- test/Sparse/Row.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sparse/Row.jl b/test/Sparse/Row.jl index 0febd16967..0ef52413d2 100644 --- a/test/Sparse/Row.jl +++ b/test/Sparse/Row.jl @@ -174,7 +174,7 @@ @test dense_row(A, 6) == matrix(FlintZZ, 1, 6, [-5, 0, 2, -10, 1, 0]) @test sparse_row(dense_row(A, 6)) == A - SRow{NCRingElem} + # SRow{NCRingElem} R = matrix_algebra(QQ,2) a = R(matrix(QQ,[1 2; 3 4])) b = R(matrix(QQ,[3 4; 5 6]))