Skip to content

Commit ae6f998

Browse files
author
Clément Fauchereau
committed
fast extrema computation on sparse arrays
1 parent bf886b5 commit ae6f998

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

stdlib/SparseArrays/src/higherorderfns.jl

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module HigherOrderFns
44

55
# This module provides higher order functions specialized for sparse arrays,
66
# particularly map[!]/broadcast[!] for SparseVectors and SparseMatrixCSCs at present.
7-
import Base: map, map!, broadcast, copy, copyto!
7+
import Base: map, map!, broadcast, copy, copyto!, extrema
88

99
using Base: front, tail, to_shape
1010
using ..SparseArrays: SparseVector, SparseMatrixCSC, AbstractSparseVector, AbstractSparseMatrixCSC,
@@ -29,6 +29,7 @@ using LinearAlgebra
2929
# (11) Define broadcast[!] methods handling combinations of scalars, sparse vectors/matrices,
3030
# structured matrices, and one- and two-dimensional Arrays.
3131
# (12) Define map[!] methods handling combinations of sparse and structured matrices.
32+
# (13) Define extrema methods optimized for sparse vectors/matrices.
3233

3334

3435
# (0) BroadcastStyle rules and convenience types for dispatch
@@ -1154,4 +1155,23 @@ map(f::Tf, A::SparseOrStructuredMatrix, Bs::Vararg{SparseOrStructuredMatrix,N})
11541155
map!(f::Tf, C::AbstractSparseMatrixCSC, A::SparseOrStructuredMatrix, Bs::Vararg{SparseOrStructuredMatrix,N}) where {Tf,N} =
11551156
(_checksameshape(C, A, Bs...); _noshapecheck_map!(f, C, _sparsifystructured(A), map(_sparsifystructured, Bs)...))
11561157

1158+
1159+
# (13) extrema methods optimized for sparse vectors/matrices.
1160+
function extrema(f, A::SparseVecOrMat)
1161+
if iszero(length(A))
1162+
throw(ArgumentError("Sparse array must have at least one element."))
1163+
end
1164+
N = nnz(A)
1165+
iszero(N) && return f(zero(eltype(A))), f(zero(eltype(A)))
1166+
vmin, vmax = extrema(f, nonzeros(A))
1167+
if N != length(A)
1168+
f0 = f(zero(eltype(A)))
1169+
vmin = min(f0, vmin)
1170+
vmax = max(f0, vmax)
1171+
end
1172+
vmin, vmax
1173+
end
1174+
1175+
extrema(A::SparseVecOrMat) = extrema(identity, A)
1176+
11571177
end

stdlib/SparseArrays/test/higherorderfns.jl

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,4 +687,23 @@ end
687687
@test SparseMatStyle(Val(3)) == Broadcast.DefaultArrayStyle{3}()
688688
end
689689

690+
@testset "extrema" begin
691+
n = 10
692+
A = sprand(n, n, 0.2)
693+
B = Array(A)
694+
x = sprand(n, 0.2)
695+
y = Array(x)
696+
f(x) = x^3
697+
@test extrema(A) == extrema(B)
698+
@test extrema(x) == extrema(y)
699+
@test extrema(f, A) == extrema(f, B)
700+
@test extrema(f, x) == extrema(f, y)
701+
@test extrema(spzeros(n, n)) == (0.0, 0.0)
702+
@test extrema(spzeros(n)) == (0.0, 0.0)
703+
@test_throws ArgumentError extrema(spzeros(0, 0))
704+
@test_throws ArgumentError extrema(spzeros(0))
705+
@test extrema(sparse(ones(n, n))) == (1.0, 1.0)
706+
@test extrema(sparse(ones(n))) == (1.0, 1.0)
707+
end
708+
690709
end # module

0 commit comments

Comments
 (0)