Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mutating arithmetic for SRows #1659

Merged
merged 11 commits into from
Nov 13, 2024
142 changes: 126 additions & 16 deletions src/Sparse/Row.jl
Original file line number Diff line number Diff line change
Expand Up @@ -447,15 +447,17 @@
# Inplace scaling
#
################################################################################

@doc raw"""
scale_row!(a::SRow, b::NCRingElem) -> SRow

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
@assert !iszero(b)
if isone(b)
if iszero(b)
return empty!(a)

Check warning on line 459 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L459

Added line #L459 was not covered by tests
elseif isone(b)
return a
end
i = 1
Expand All @@ -465,20 +467,23 @@
deleteat!(a.values, i)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Orthogonal to this PR, but: Since you now handle b==0 at the start, the iszero(a.values[i]) check above the fold can only return true if the coefficient ring is not a domain. So it could be strengthened to something like !is_domain_type(T) && iszero(a.values[i]).

Since is_domain_type is a trait depending only on T, the compiler can eliminate the is_domain_type(T) check -- if it returns true it can elide the if block, and if it is false we the same code we have currently.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this can easily wait for a follow-up PR. (Also scale_row! and scale_row_right! could be merged)

deleteat!(a.pos, i)
else
i += 1
i += 1
end
end
return a
end

scale_row!(a::SRow, b) = scale_row!(a, base_ring(a)(b))

Check warning on line 476 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L476

Added line #L476 was not covered by tests

@doc raw"""
scale_row_right!(a::SRow, b::NCRingElem) -> SRow

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)
if isone(b)
if iszero(b)
return empty!(a)

Check warning on line 485 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L485

Added line #L485 was not covered by tests
elseif isone(b)
return a
end
i = 1
Expand All @@ -488,16 +493,20 @@
deleteat!(a.values, i)
deleteat!(a.pos, i)
else
i += 1
i += 1
end
end
return a
end

scale_row_right!(a::SRow, b) = scale_row_right!(a, base_ring(a)(b))

Check warning on line 502 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L502

Added line #L502 was not covered by tests

function scale_row_left!(a::SRow{T}, b::T) where T
return scale_row!(a,b)
end

scale_row_left!(a::SRow, b) = scale_row_left!(a, base_ring(a)(b))

Check warning on line 508 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L508

Added line #L508 was not covered by tests

################################################################################
#
# Addition
Expand All @@ -518,10 +527,10 @@
if length(B) == 0
return A
else
return add_scaled_row(B, A, base_ring(B)(-1))
return add_scaled_row(B, A, -1)
end
end
return add_scaled_row(B, A, base_ring(A)(-1))
return add_scaled_row(B, A, -1)
end

function -(A::SRow{T}) where {T}
Expand Down Expand Up @@ -683,10 +692,10 @@

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_scaled_row(a::SRow{T}, b::SRow{T}, c) where {T} = add_scaled_row!(a, deepcopy(b), c)

add_left_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_left_scaled_row!(a, deepcopy(b), c)
add_right_scaled_row(a::SRow{T}, b::SRow{T}, c::T) where {T} = add_right_scaled_row!(a, deepcopy(b), c)
add_left_scaled_row(a::SRow{T}, b::SRow{T}, c) where {T} = add_left_scaled_row!(a, deepcopy(b), c)
add_right_scaled_row(a::SRow{T}, b::SRow{T}, c) where {T} = add_right_scaled_row!(a, deepcopy(b), c)

Check warning on line 698 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L697-L698

Added lines #L697 - L698 were not covered by tests



Expand All @@ -696,7 +705,9 @@
Adds the left scaled row $c A$ to $B$.
"""
function add_scaled_row!(a::SRow{T}, b::SRow{T}, c::T, ::Val{left_side} = Val(true)) where {T, left_side}
@assert a !== b
if a === b
a = deepcopy(a)

Check warning on line 709 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L709

Added line #L709 was not covered by tests
end
i = 1
j = 1
t = base_ring(a)()
Expand Down Expand Up @@ -735,17 +746,116 @@
return b
end

add_scaled_row!(a::SRow{T}, b::SRow{T}, c) where {T} = add_scaled_row!(a, b, base_ring(a)(c))

add_scaled_row!(a::SRow{T}, b::SRow{T}, c, side::Val) where {T} = add_scaled_row!(a, b, base_ring(a)(c), side)

Check warning on line 751 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L751

Added line #L751 was not covered by tests

# ignore tmp argument
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, tmp::SRow{T}) where T = add_scaled_row!(a, b, c)

Check warning on line 754 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L754

Added line #L754 was not covered by tests

add_left_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T = add_scaled_row!(a, b, c)
add_left_scaled_row!(a::SRow{T}, b::SRow{T}, c) where T = add_scaled_row!(a, b, c)

Check warning on line 756 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L756

Added line #L756 was not covered by tests

@doc raw"""
add_right_scaled_row!(A::SRow{T}, B::SRow{T}, c::T) -> SRow{T}

Return the right scaled row $c A$ to $B$ by changing $B$ in place.
Return the right scaled row $A c$ to $B$ by changing $B$ in place.
"""
add_right_scaled_row!(a::SRow{T}, b::SRow{T}, c::T) where T = add_scaled_row!(a, b, c, Val(false))
add_right_scaled_row!(a::SRow{T}, b::SRow{T}, c) where T = add_scaled_row!(a, b, c, Val(false))


################################################################################
#
# Mutating arithmetics
#
################################################################################

function zero!(z::SRow)
return empty!(z)

Check warning on line 773 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L772-L773

Added lines #L772 - L773 were not covered by tests
end

function neg!(z::SRow{T}, x::SRow{T}) where T
if z === x
return neg!(x)

Check warning on line 778 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L776-L778

Added lines #L776 - L778 were not covered by tests
end
swap!(z, -x)
return z

Check warning on line 781 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L780-L781

Added lines #L780 - L781 were not covered by tests
end

function neg!(z::SRow)
for i in 1:length(z)
z.values[i] = neg!(z.values[i])
end
return z

Check warning on line 788 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L784-L788

Added lines #L784 - L788 were not covered by tests
end

function add!(z::SRow{T}, x::SRow{T}, y::SRow{T}) where T
if z === x
return add!(x, y)
elseif z === y
return add!(y, x)

Check warning on line 795 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L791-L795

Added lines #L791 - L795 were not covered by tests
end
swap!(z, x + y)
return z

Check warning on line 798 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L797-L798

Added lines #L797 - L798 were not covered by tests
end

function add!(z::SRow{T}, x::SRow{T}) where T
if z === x
return scale_row!(z, 2)

Check warning on line 803 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L801-L803

Added lines #L801 - L803 were not covered by tests
end
return add_scaled_row!(x, z, one(base_ring(x)))

Check warning on line 805 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L805

Added line #L805 was not covered by tests
end

function sub!(z::SRow{T}, x::SRow{T}, y::SRow{T}) where T
if z === x
return sub!(x, y)
elseif z === y
return neg!(sub!(y, x))

Check warning on line 812 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L808-L812

Added lines #L808 - L812 were not covered by tests
end
swap!(z, x - y)
return z

Check warning on line 815 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L814-L815

Added lines #L814 - L815 were not covered by tests
end

function sub!(z::SRow{T}, x::SRow{T}) where T
if z === x
return empty!(z)

Check warning on line 820 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L818-L820

Added lines #L818 - L820 were not covered by tests
end
return add_scaled_row!(x, z, -1)

Check warning on line 822 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L822

Added line #L822 was not covered by tests
end

function mul!(z::SRow{T}, x::SRow{T}, c) where T
if z === x
return scale_row_right!(x, c)

Check warning on line 827 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L825-L827

Added lines #L825 - L827 were not covered by tests
end
swap!(z, x * c)
return z

Check warning on line 830 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L829-L830

Added lines #L829 - L830 were not covered by tests
end

function mul!(z::SRow{T}, c, y::SRow{T}) where T
if z === y
return scale_row_left!(y, c)

Check warning on line 835 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L833-L835

Added lines #L833 - L835 were not covered by tests
end
swap!(z, c * y)
return z

Check warning on line 838 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L837-L838

Added lines #L837 - L838 were not covered by tests
end

function addmul!(z::SRow{T}, x::SRow{T}, y) where T
if z === x
return scale_row_right!(x, y+1)

Check warning on line 843 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L841-L843

Added lines #L841 - L843 were not covered by tests
end
return add_right_scaled_row!(x, z, y)

Check warning on line 845 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L845

Added line #L845 was not covered by tests
end

function addmul!(z::SRow{T}, x, y::SRow{T}) where T
if z === x
return scale_row_left!(y, x+1)

Check warning on line 850 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L848-L850

Added lines #L848 - L850 were not covered by tests
end
return add_left_scaled_row!(y, z, x)

Check warning on line 852 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L852

Added line #L852 was not covered by tests
end


# ignore temp variable
addmul!(z::SRow{T}, x::SRow{T}, y, t) where T = addmul!(z, x, y)
addmul!(z::SRow{T}, x, y::SRow{T}, t) where T = addmul!(z, x, y)

Check warning on line 858 in src/Sparse/Row.jl

View check run for this annotation

Codecov / codecov/patch

src/Sparse/Row.jl#L857-L858

Added lines #L857 - L858 were not covered by tests


################################################################################
Expand Down
Loading