From 87c311f8e55eb851e6bee2d040521ad84a5c6098 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Mon, 8 Jul 2024 16:22:34 +0100 Subject: [PATCH 01/14] add sum without dims --- src/BandedMatrices.jl | 1 + src/banded/BandedMatrix.jl | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index ff9b760a..0d89c893 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -99,4 +99,5 @@ end include("precompile.jl") + end #module diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index f38834cf..065a4956 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1007,3 +1007,24 @@ function resize(A::BandedSubBandedMatrix, n::Integer, m::Integer) l,u = bandwidths(A) _BandedMatrix(reshape(resize!(vec(copy(bandeddata(A))), (l+u+1)*m), l+u+1, m), n, l,u) end + +function Base.sum(A::BandedMatrix) + l,u = bandwidths(A) + height,width = size(A) + lower, upper = min(height-1,l), min(width-1,u) + data = zeros(1+lower+upper,min(height,width)) + for i=-lower:upper + b = A[band(i)] + data[i+lower+1,1:length(b)] = b + end + sum(data) +end + +function Base.sum(A::BandedMatrix; dims) + if(dims > 2) + A + elseif(dims == 2) + A + end +end + From b6530b905464e28c4312679e41a610257d98dd11 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Mon, 8 Jul 2024 16:35:09 +0100 Subject: [PATCH 02/14] add sum; dims=1 --- src/banded/BandedMatrix.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 065a4956..4cf9a892 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1011,6 +1011,7 @@ end function Base.sum(A::BandedMatrix) l,u = bandwidths(A) height,width = size(A) + #Only get nonempty bands lower, upper = min(height-1,l), min(width-1,u) data = zeros(1+lower+upper,min(height,width)) for i=-lower:upper @@ -1025,6 +1026,17 @@ function Base.sum(A::BandedMatrix; dims) A elseif(dims == 2) A + elseif(dims == 1) + l,u = bandwidths(A) + height,width = size(A) + #Only get nonempty bands + lower, upper = min(height-1,l), min(width-1,u) + data = zeros(1+lower+upper,min(height,width)) + for i=-lower:upper + b = A[band(i)] + data[i+lower+1,(i <= 0 ? (1:length(b)) : (end-length(b)+1:end))] = b + end + sum(data; dims=1) end end From bec277e9e79ee8e1effb6e1c01e8b83ac59e10af Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Mon, 8 Jul 2024 22:45:22 +0100 Subject: [PATCH 03/14] support for dims = 2 and error handling --- src/banded/BandedMatrix.jl | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 4cf9a892..6abd3013 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1025,18 +1025,29 @@ function Base.sum(A::BandedMatrix; dims) if(dims > 2) A elseif(dims == 2) - A + l,u = bandwidths(A) + height,width = size(A) + #Only get nonempty bands + lower, upper = min(height-1,l), min(width-1,u) + data = zeros(height,1+lower+upper) + for i=-lower:upper + b = A[band(i)] + data[(i > 0 ? (1:length(b)) : (1-i:length(b)-i)),i+lower+1] = b + end + sum(data; dims=2) elseif(dims == 1) l,u = bandwidths(A) height,width = size(A) #Only get nonempty bands lower, upper = min(height-1,l), min(width-1,u) - data = zeros(1+lower+upper,min(height,width)) + data = zeros(1+lower+upper,width) for i=-lower:upper b = A[band(i)] - data[i+lower+1,(i <= 0 ? (1:length(b)) : (end-length(b)+1:end))] = b + data[i+lower+1,(i <= 0 ? (1:length(b)) : (i+1:i+length(b)))] = b end - sum(data; dims=1) + sum(data;dims=1) + else + throw(ArgumentError("dimension must be ≥ 1, got $dims")) end end From cd92d7f0caab3067c8ae89e616c86b89ed3a2b66 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Mon, 8 Jul 2024 23:07:32 +0100 Subject: [PATCH 04/14] fix for empty matrices and added unit tests --- src/banded/BandedMatrix.jl | 14 ++++++++++++-- test/test_sum.jl | 11 +++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 test/test_sum.jl diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 6abd3013..924f0c99 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1010,6 +1010,10 @@ end function Base.sum(A::BandedMatrix) l,u = bandwidths(A) + #For empty matrices + if(l + u < 0) + return convert(eltype(A),0) + end height,width = size(A) #Only get nonempty bands lower, upper = min(height-1,l), min(width-1,u) @@ -1027,18 +1031,24 @@ function Base.sum(A::BandedMatrix; dims) elseif(dims == 2) l,u = bandwidths(A) height,width = size(A) - #Only get nonempty bands + if(l + u < 0) + return zeros(eltype(A),(height,1)) + end lower, upper = min(height-1,l), min(width-1,u) + #dimension of interest preserved data = zeros(height,1+lower+upper) for i=-lower:upper b = A[band(i)] + #populates data array in such a way that everything along the same axis of interest is aligned data[(i > 0 ? (1:length(b)) : (1-i:length(b)-i)),i+lower+1] = b end sum(data; dims=2) elseif(dims == 1) l,u = bandwidths(A) height,width = size(A) - #Only get nonempty bands + if(l + u < 0) + return zeros(eltype(A),(1,width)) + end lower, upper = min(height-1,l), min(width-1,u) data = zeros(1+lower+upper,width) for i=-lower:upper diff --git a/test/test_sum.jl b/test/test_sum.jl new file mode 100644 index 00000000..1acc84cc --- /dev/null +++ b/test/test_sum.jl @@ -0,0 +1,11 @@ +using Test, BandedMatrices, Random + +r = brand(Float64,rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) +matr = Matrix(r) +@testset "sum" begin + @test sum(r) ≈ sum(Matrix(r)) atol = 1e-8 + @test sum(r; dims=2) ≈ sum(Matrix(r); dims=2) atol = 1e-8 + @test sum(r; dims=1) ≈ sum(Matrix(r); dims=1) atol = 1e-8 + @test sum(r; dims=3) == r + @test_throws ArgumentError sum(r; dims=0) +end \ No newline at end of file From 0768d344f3a215a0ddff1fd870b7c8bd504b4838 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Mon, 8 Jul 2024 23:46:08 +0100 Subject: [PATCH 05/14] style --- src/banded/BandedMatrix.jl | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 924f0c99..9ca282d0 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1029,33 +1029,33 @@ function Base.sum(A::BandedMatrix; dims) if(dims > 2) A elseif(dims == 2) - l,u = bandwidths(A) - height,width = size(A) + l, u = bandwidths(A) + height, width = size(A) if(l + u < 0) - return zeros(eltype(A),(height,1)) + return zeros(eltype(A), (height, 1)) end - lower, upper = min(height-1,l), min(width-1,u) + lower, upper = min(height-1, l), min(width-1, u) #dimension of interest preserved - data = zeros(height,1+lower+upper) + data = zeros(height, 1+lower+upper) for i=-lower:upper b = A[band(i)] #populates data array in such a way that everything along the same axis of interest is aligned - data[(i > 0 ? (1:length(b)) : (1-i:length(b)-i)),i+lower+1] = b + data[(i > 0 ? (1:length(b)) : (1-i:length(b)-i)), i+lower+1] = b end sum(data; dims=2) elseif(dims == 1) - l,u = bandwidths(A) - height,width = size(A) + l, u = bandwidths(A) + height, width = size(A) if(l + u < 0) - return zeros(eltype(A),(1,width)) + return zeros(eltype(A), (1,width)) end - lower, upper = min(height-1,l), min(width-1,u) - data = zeros(1+lower+upper,width) + lower, upper = min(height-1, l), min(width-1, u) + data = zeros(1+lower+upper, width) for i=-lower:upper b = A[band(i)] - data[i+lower+1,(i <= 0 ? (1:length(b)) : (i+1:i+length(b)))] = b + data[i+lower+1, (i <= 0 ? (1:length(b)) : (i+1:i+length(b)))] = b end - sum(data;dims=1) + sum(data; dims=1) else throw(ArgumentError("dimension must be ≥ 1, got $dims")) end From cb197f5d06164f7469116c14873aafc71678f350 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Tue, 9 Jul 2024 14:17:19 +0100 Subject: [PATCH 06/14] make improvements --- src/BandedMatrices.jl | 2 +- src/banded/BandedMatrix.jl | 58 ++++++++++++++++++++------------------ test/test_sum.jl | 6 ++-- 3 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index 0d89c893..c6584dc0 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -7,7 +7,7 @@ import Base: axes, axes1, getproperty, getindex, setindex!, *, +, -, ==, <, <=, >=, /, \, adjoint, transpose, showerror, convert, size, view, unsafe_indices, first, last, size, length, unsafe_length, step, to_indices, to_index, show, fill!, similar, copy, promote_rule, real, imag, - copyto!, Array + copyto!, Array, sum using Base.Broadcast: AbstractArrayStyle, DefaultArrayStyle, Broadcasted import Base.Broadcast: BroadcastStyle, broadcasted diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 9ca282d0..15e55f3e 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1008,54 +1008,58 @@ function resize(A::BandedSubBandedMatrix, n::Integer, m::Integer) _BandedMatrix(reshape(resize!(vec(copy(bandeddata(A))), (l+u+1)*m), l+u+1, m), n, l,u) end -function Base.sum(A::BandedMatrix) - l,u = bandwidths(A) - #For empty matrices +function sum(A::BandedMatrix) + l, u = bandwidths(A) + ret = zero(eltype(A)) if(l + u < 0) - return convert(eltype(A),0) + return ret end - height,width = size(A) + n, m = size(A) #Only get nonempty bands - lower, upper = min(height-1,l), min(width-1,u) - data = zeros(1+lower+upper,min(height,width)) - for i=-lower:upper - b = A[band(i)] - data[i+lower+1,1:length(b)] = b + lower, upper = min(n-1, l), min(m-1, u) + for i = -lower:upper + ret += sum(A[band(i)]) end - sum(data) + ret end -function Base.sum(A::BandedMatrix; dims) +function sum(A::BandedMatrix; dims) if(dims > 2) A elseif(dims == 2) l, u = bandwidths(A) - height, width = size(A) + n, m = size(A) + ret = zeros(eltype(A), (n, 1)) if(l + u < 0) - return zeros(eltype(A), (height, 1)) + return ret end - lower, upper = min(height-1, l), min(width-1, u) - #dimension of interest preserved - data = zeros(height, 1+lower+upper) - for i=-lower:upper + lower, upper = min(n-1, l), min(m-1, u) + for i = -lower:upper b = A[band(i)] - #populates data array in such a way that everything along the same axis of interest is aligned - data[(i > 0 ? (1:length(b)) : (1-i:length(b)-i)), i+lower+1] = b + if(i <= 0) + ret[1-i:length(b)-i, 1] += b + else + ret[1:length(b), 1] += b + end end - sum(data; dims=2) + ret elseif(dims == 1) l, u = bandwidths(A) - height, width = size(A) + n, m = size(A) + ret = zeros(eltype(A), (1, m)) if(l + u < 0) - return zeros(eltype(A), (1,width)) + return ret end - lower, upper = min(height-1, l), min(width-1, u) - data = zeros(1+lower+upper, width) + lower, upper = min(n-1, l), min(m-1, u) for i=-lower:upper b = A[band(i)] - data[i+lower+1, (i <= 0 ? (1:length(b)) : (i+1:i+length(b)))] = b + if(i <= 0) + ret[1, 1:length(b)] += b + else + ret[1, i+1:i+length(b)] += b + end end - sum(data; dims=1) + ret else throw(ArgumentError("dimension must be ≥ 1, got $dims")) end diff --git a/test/test_sum.jl b/test/test_sum.jl index 1acc84cc..96c42da4 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -3,9 +3,9 @@ using Test, BandedMatrices, Random r = brand(Float64,rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) matr = Matrix(r) @testset "sum" begin - @test sum(r) ≈ sum(Matrix(r)) atol = 1e-8 - @test sum(r; dims=2) ≈ sum(Matrix(r); dims=2) atol = 1e-8 - @test sum(r; dims=1) ≈ sum(Matrix(r); dims=1) atol = 1e-8 + @test sum(r) ≈ sum(matr) atol = 1e-10 + @test sum(r; dims=2) ≈ sum(matr; dims=2) atol = 1e-10 + @test sum(r; dims=1) ≈ sum(matr; dims=1) atol = 1e-10 @test sum(r; dims=3) == r @test_throws ArgumentError sum(r; dims=0) end \ No newline at end of file From d0109be4ab1f8f5fe2e3cb20fc7b0d03cc364063 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Tue, 9 Jul 2024 14:42:53 +0100 Subject: [PATCH 07/14] add test_sum.jl to runtests.jl --- test/runtests.jl | 1 + test/test_sum.jl | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 2e536839..7778453b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -26,3 +26,4 @@ include("test_symbanded.jl") include("test_tribanded.jl") include("test_interface.jl") include("test_miscs.jl") +include("test_sum.jl") diff --git a/test/test_sum.jl b/test/test_sum.jl index 96c42da4..ff37f95f 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -1,3 +1,5 @@ +module TestSum + using Test, BandedMatrices, Random r = brand(Float64,rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) @@ -8,4 +10,6 @@ matr = Matrix(r) @test sum(r; dims=1) ≈ sum(matr; dims=1) atol = 1e-10 @test sum(r; dims=3) == r @test_throws ArgumentError sum(r; dims=0) +end + end \ No newline at end of file From 8da60dfe142b0895c4e083c17d2593f87314816e Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Tue, 9 Jul 2024 15:26:37 +0100 Subject: [PATCH 08/14] fix method dispatch issue in a way that mimics Base.sum --- src/banded/BandedMatrix.jl | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 15e55f3e..57cdf3e0 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1008,23 +1008,21 @@ function resize(A::BandedSubBandedMatrix, n::Integer, m::Integer) _BandedMatrix(reshape(resize!(vec(copy(bandeddata(A))), (l+u+1)*m), l+u+1, m), n, l,u) end -function sum(A::BandedMatrix) - l, u = bandwidths(A) - ret = zero(eltype(A)) - if(l + u < 0) - return ret - end - n, m = size(A) - #Only get nonempty bands - lower, upper = min(n-1, l), min(m-1, u) - for i = -lower:upper - ret += sum(A[band(i)]) - end - ret -end - -function sum(A::BandedMatrix; dims) - if(dims > 2) +function sum(A::BandedMatrix; dims=:) + if(dims == :) + l, u = bandwidths(A) + ret = zero(eltype(A)) + if(l + u < 0) + return ret + end + n, m = size(A) + #Only get nonempty bands + lower, upper = min(n-1, l), min(m-1, u) + for i = -lower:upper + ret += sum(A[band(i)]) + end + ret + elseif(dims > 2) A elseif(dims == 2) l, u = bandwidths(A) From de15c533982793938ef91cf8848537c500f0ee7a Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Wed, 10 Jul 2024 14:03:53 +0100 Subject: [PATCH 09/14] update unit tests, reduce memory allocation, improve style --- src/banded/BandedMatrix.jl | 44 +++++++++++++------------------------- test/test_sum.jl | 11 +++++++--- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 57cdf3e0..70037d4a 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1009,53 +1009,39 @@ function resize(A::BandedSubBandedMatrix, n::Integer, m::Integer) end function sum(A::BandedMatrix; dims=:) - if(dims == :) + if dims isa Colon l, u = bandwidths(A) ret = zero(eltype(A)) - if(l + u < 0) + if l + u < 0 return ret end n, m = size(A) - #Only get nonempty bands - lower, upper = min(n-1, l), min(m-1, u) - for i = -lower:upper - ret += sum(A[band(i)]) + for i = 1:n, j = rowrange(A, i) + ret += A[i, j] end ret - elseif(dims > 2) + elseif dims > 2 A - elseif(dims == 2) + elseif dims == 2 l, u = bandwidths(A) n, m = size(A) - ret = zeros(eltype(A), (n, 1)) - if(l + u < 0) + ret = zeros(eltype(A), n, 1) + if l + u < 0 return ret end - lower, upper = min(n-1, l), min(m-1, u) - for i = -lower:upper - b = A[band(i)] - if(i <= 0) - ret[1-i:length(b)-i, 1] += b - else - ret[1:length(b), 1] += b - end + for i = 1:n, j = rowrange(A, i) + ret[i, 1] += A[i, j] end ret - elseif(dims == 1) + elseif dims == 1 l, u = bandwidths(A) n, m = size(A) - ret = zeros(eltype(A), (1, m)) - if(l + u < 0) + ret = zeros(eltype(A), 1, m) + if l + u < 0 return ret end - lower, upper = min(n-1, l), min(m-1, u) - for i=-lower:upper - b = A[band(i)] - if(i <= 0) - ret[1, 1:length(b)] += b - else - ret[1, i+1:i+length(b)] += b - end + for i = 1:m, j = colrange(A, i) + ret[1, i] += A[j, i] end ret else diff --git a/test/test_sum.jl b/test/test_sum.jl index ff37f95f..54aee662 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -3,11 +3,16 @@ module TestSum using Test, BandedMatrices, Random r = brand(Float64,rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) +empty_r = brand(Float64,rand(1:1_000),rand(1:1_000),rand(1:100),rand(-200:-101)) +n,m = size(empty_r) matr = Matrix(r) @testset "sum" begin - @test sum(r) ≈ sum(matr) atol = 1e-10 - @test sum(r; dims=2) ≈ sum(matr; dims=2) atol = 1e-10 - @test sum(r; dims=1) ≈ sum(matr; dims=1) atol = 1e-10 + @test sum(empty_r) ≈ 0 + @test sum(empty_r; dims = 2) ≈ zeros(n,1) + @test sum(empty_r; dims = 1) ≈ zeros(1,m) + @test sum(r) ≈ sum(matr) rtol = 1e-10 + @test sum(r; dims=2) ≈ sum(matr; dims=2) rtol = 1e-10 + @test sum(r; dims=1) ≈ sum(matr; dims=1) rtol = 1e-10 @test sum(r; dims=3) == r @test_throws ArgumentError sum(r; dims=0) end From 0e0bc12ed40067f60d55b605ea4f81b594479163 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Wed, 10 Jul 2024 16:15:19 +0100 Subject: [PATCH 10/14] update unit tests, add sum!, move to AbstractBandedMatrix.jl --- src/BandedMatrices.jl | 2 +- src/banded/BandedMatrix.jl | 41 ------------------- src/generic/AbstractBandedMatrix.jl | 63 +++++++++++++++++++++++++++++ test/test_sum.jl | 12 +++--- 4 files changed, 70 insertions(+), 48 deletions(-) diff --git a/src/BandedMatrices.jl b/src/BandedMatrices.jl index c6584dc0..5028f2ea 100644 --- a/src/BandedMatrices.jl +++ b/src/BandedMatrices.jl @@ -7,7 +7,7 @@ import Base: axes, axes1, getproperty, getindex, setindex!, *, +, -, ==, <, <=, >=, /, \, adjoint, transpose, showerror, convert, size, view, unsafe_indices, first, last, size, length, unsafe_length, step, to_indices, to_index, show, fill!, similar, copy, promote_rule, real, imag, - copyto!, Array, sum + copyto!, Array, sum, sum! using Base.Broadcast: AbstractArrayStyle, DefaultArrayStyle, Broadcasted import Base.Broadcast: BroadcastStyle, broadcasted diff --git a/src/banded/BandedMatrix.jl b/src/banded/BandedMatrix.jl index 70037d4a..4d1909fb 100644 --- a/src/banded/BandedMatrix.jl +++ b/src/banded/BandedMatrix.jl @@ -1008,44 +1008,3 @@ function resize(A::BandedSubBandedMatrix, n::Integer, m::Integer) _BandedMatrix(reshape(resize!(vec(copy(bandeddata(A))), (l+u+1)*m), l+u+1, m), n, l,u) end -function sum(A::BandedMatrix; dims=:) - if dims isa Colon - l, u = bandwidths(A) - ret = zero(eltype(A)) - if l + u < 0 - return ret - end - n, m = size(A) - for i = 1:n, j = rowrange(A, i) - ret += A[i, j] - end - ret - elseif dims > 2 - A - elseif dims == 2 - l, u = bandwidths(A) - n, m = size(A) - ret = zeros(eltype(A), n, 1) - if l + u < 0 - return ret - end - for i = 1:n, j = rowrange(A, i) - ret[i, 1] += A[i, j] - end - ret - elseif dims == 1 - l, u = bandwidths(A) - n, m = size(A) - ret = zeros(eltype(A), 1, m) - if l + u < 0 - return ret - end - for i = 1:m, j = colrange(A, i) - ret[1, i] += A[j, i] - end - ret - else - throw(ArgumentError("dimension must be ≥ 1, got $dims")) - end -end - diff --git a/src/generic/AbstractBandedMatrix.jl b/src/generic/AbstractBandedMatrix.jl index 55d1668a..0abeef70 100644 --- a/src/generic/AbstractBandedMatrix.jl +++ b/src/generic/AbstractBandedMatrix.jl @@ -336,3 +336,66 @@ if VERSION >= v"1.9" copy(A::Adjoint{T,<:AbstractBandedMatrix}) where T = copy(parent(A))' copy(A::Transpose{T,<:AbstractBandedMatrix}) where T = transpose(copy(parent(A))) end + +function sum!(ret::AbstractArray, A::AbstractBandedMatrix) + #Behaves similarly to Base.sum! + ret .= 0 + n,m = size(A) + s = size(ret) + l = length(s) + #Check for singleton dimension and perform respective sum + if s[1] == 1 && (l == 1 || s[2]==1) + for j = 1:m, i = colrange(A, j) + ret .+= A[i, j] + end + elseif s[1] == n && (l == 1 || s[2]==1) + for i = 1:n, j = rowrange(A, i) + ret[i, 1] += A[i, j] + end + elseif s[1] == 1 && s[2] == m + for j = 1:m, i = colrange(A, j) + ret[1, j] += A[i, j] + end + elseif s[1] == n && s[2] == m + ret = A + else + throw(DimensionMismatch("reduction on matrix of size ($n, $m) with output size $s")) + end +end + +function sum(A::AbstractBandedMatrix; dims=:) + if dims isa Colon + l, u = bandwidths(A) + ret = zero(eltype(A)) + if l + u < 0 + return ret + end + n, m = size(A) + for j = 1:m, i = colrange(A, j) + ret += A[i, j] + end + ret + elseif dims > 2 + A + elseif dims == 2 + l, u = bandwidths(A) + n, m = size(A) + ret = zeros(eltype(A), n, 1) + if l + u < 0 + return ret + end + sum!(ret, A) + ret + elseif dims == 1 + l, u = bandwidths(A) + n, m = size(A) + ret = zeros(eltype(A), 1, m) + if l + u < 0 + return ret + end + sum!(ret, A) + ret + else + throw(ArgumentError("dimension must be ≥ 1, got $dims")) + end +end diff --git a/test/test_sum.jl b/test/test_sum.jl index 54aee662..9a248e08 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -7,12 +7,12 @@ empty_r = brand(Float64,rand(1:1_000),rand(1:1_000),rand(1:100),rand(-200:-101)) n,m = size(empty_r) matr = Matrix(r) @testset "sum" begin - @test sum(empty_r) ≈ 0 - @test sum(empty_r; dims = 2) ≈ zeros(n,1) - @test sum(empty_r; dims = 1) ≈ zeros(1,m) - @test sum(r) ≈ sum(matr) rtol = 1e-10 - @test sum(r; dims=2) ≈ sum(matr; dims=2) rtol = 1e-10 - @test sum(r; dims=1) ≈ sum(matr; dims=1) rtol = 1e-10 + @test sum(empty_r) == 0 + @test sum(empty_r; dims = 2) == zeros(n,1) + @test sum(empty_r; dims = 1) == zeros(1,m) + @test sum(r) == sum(matr) + @test sum(r; dims=2) == sum(matr; dims=2) + @test sum(r; dims=1) == sum(matr; dims=1) @test sum(r; dims=3) == r @test_throws ArgumentError sum(r; dims=0) end From cfc895e39ce5e5854d00a9b707b0ae5c8ccb6798 Mon Sep 17 00:00:00 2001 From: Maxim Vassiliev Date: Mon, 15 Jul 2024 15:38:15 +0100 Subject: [PATCH 11/14] revert tests to \approx --- test/test_sum.jl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test_sum.jl b/test/test_sum.jl index 9a248e08..a599dc09 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -10,9 +10,9 @@ matr = Matrix(r) @test sum(empty_r) == 0 @test sum(empty_r; dims = 2) == zeros(n,1) @test sum(empty_r; dims = 1) == zeros(1,m) - @test sum(r) == sum(matr) - @test sum(r; dims=2) == sum(matr; dims=2) - @test sum(r; dims=1) == sum(matr; dims=1) + @test sum(r) ≈ sum(matr) rtol = 1e-10 + @test sum(r; dims=2) ≈ sum(matr; dims=2) rtol = 1e-10 + @test sum(r; dims=1) ≈ sum(matr; dims=1) rtol = 1e-10 @test sum(r; dims=3) == r @test_throws ArgumentError sum(r; dims=0) end From dc9a82d7c4e9465e2a871e6663ef89a7397d031f Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Tue, 16 Jul 2024 14:07:39 +0100 Subject: [PATCH 12/14] make improvements in AbstractBandedMatrix.jl --- src/generic/AbstractBandedMatrix.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/generic/AbstractBandedMatrix.jl b/src/generic/AbstractBandedMatrix.jl index 0abeef70..8e714972 100644 --- a/src/generic/AbstractBandedMatrix.jl +++ b/src/generic/AbstractBandedMatrix.jl @@ -339,7 +339,7 @@ end function sum!(ret::AbstractArray, A::AbstractBandedMatrix) #Behaves similarly to Base.sum! - ret .= 0 + fill!(ret, zero(eltype(ret))) n,m = size(A) s = size(ret) l = length(s) @@ -357,7 +357,7 @@ function sum!(ret::AbstractArray, A::AbstractBandedMatrix) ret[1, j] += A[i, j] end elseif s[1] == n && s[2] == m - ret = A + copyto!(ret,A) else throw(DimensionMismatch("reduction on matrix of size ($n, $m) with output size $s")) end From 393bf6218c0cfde36e86580c370c002cf3fed813 Mon Sep 17 00:00:00 2001 From: maximvassiliev Date: Tue, 16 Jul 2024 14:46:29 +0100 Subject: [PATCH 13/14] test special cases of sum! --- src/generic/AbstractBandedMatrix.jl | 2 ++ test/test_sum.jl | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/generic/AbstractBandedMatrix.jl b/src/generic/AbstractBandedMatrix.jl index 8e714972..c5653c26 100644 --- a/src/generic/AbstractBandedMatrix.jl +++ b/src/generic/AbstractBandedMatrix.jl @@ -361,6 +361,8 @@ function sum!(ret::AbstractArray, A::AbstractBandedMatrix) else throw(DimensionMismatch("reduction on matrix of size ($n, $m) with output size $s")) end + #return the value to mimic Base.sum! + ret end function sum(A::AbstractBandedMatrix; dims=:) diff --git a/test/test_sum.jl b/test/test_sum.jl index a599dc09..5ca30fd0 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -2,6 +2,7 @@ module TestSum using Test, BandedMatrices, Random +Random.seed!(0) r = brand(Float64,rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) empty_r = brand(Float64,rand(1:1_000),rand(1:1_000),rand(1:100),rand(-200:-101)) n,m = size(empty_r) @@ -10,11 +11,20 @@ matr = Matrix(r) @test sum(empty_r) == 0 @test sum(empty_r; dims = 2) == zeros(n,1) @test sum(empty_r; dims = 1) == zeros(1,m) + @test sum(r) ≈ sum(matr) rtol = 1e-10 @test sum(r; dims=2) ≈ sum(matr; dims=2) rtol = 1e-10 @test sum(r; dims=1) ≈ sum(matr; dims=1) rtol = 1e-10 @test sum(r; dims=3) == r @test_throws ArgumentError sum(r; dims=0) + + v = [1.0] + sum!(v, r) + @test v == sum!(v, Matrix(r)) + n2, m2 = size(r) + v = ones(Float64, n2) + @test sum!(v, r) == sum!(v, Matrix(r)) + @test_throws DimensionMismatch sum!(zeros(Float64, n2 + 1, m2 + 1), r) end end \ No newline at end of file From 5ec4b3cdeb59847a87124ee9a189d792b13810ff Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 16 Jul 2024 19:55:42 +0100 Subject: [PATCH 14/14] add some tests and avoid CI failure --- test/test_broadcasting.jl | 2 +- test/test_sum.jl | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/test_broadcasting.jl b/test/test_broadcasting.jl index 720d2e4a..333e1f17 100644 --- a/test/test_broadcasting.jl +++ b/test/test_broadcasting.jl @@ -26,7 +26,7 @@ Random.seed!(0) @test identity.(A) isa BandedMatrix @test bandwidths(identity.(A)) == bandwidths(A) - @test (z -> exp(z)-1).(A) == (z -> exp(z)-1).(Matrix(A)) + @test (z -> exp(z)-1).(A) ≈ (z -> exp(z)-1).(Matrix(A)) # for some reason == is breaking on Mac CI @test (z -> exp(z)-1).(A) isa BandedMatrix @test bandwidths((z -> exp(z)-1).(A)) == bandwidths(A) diff --git a/test/test_sum.jl b/test/test_sum.jl index 5ca30fd0..af08e767 100644 --- a/test/test_sum.jl +++ b/test/test_sum.jl @@ -3,8 +3,8 @@ module TestSum using Test, BandedMatrices, Random Random.seed!(0) -r = brand(Float64,rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) -empty_r = brand(Float64,rand(1:1_000),rand(1:1_000),rand(1:100),rand(-200:-101)) +r = brand(rand(1:10_000),rand(1:10_000),rand(-20:100),rand(-20:100)) +empty_r = brand(rand(1:1_000),rand(1:1_000),rand(1:100),rand(-200:-101)) n,m = size(empty_r) matr = Matrix(r) @testset "sum" begin @@ -22,8 +22,12 @@ matr = Matrix(r) sum!(v, r) @test v == sum!(v, Matrix(r)) n2, m2 = size(r) - v = ones(Float64, n2) + v = ones(n2) @test sum!(v, r) == sum!(v, Matrix(r)) + V = zeros(1,m2) + @test sum!(V, r) === V ≈ sum!(zeros(1,m2), Matrix(r)) + V = zeros(n2,m2) + @test sum!(V, r) === V == r @test_throws DimensionMismatch sum!(zeros(Float64, n2 + 1, m2 + 1), r) end