LCOV - code coverage report
Current view: top level - src - spmap.jl (source / functions) Hit Total Coverage
Test: on branch nothing Lines: 65 67 97.0 %
Date: 2025-01-21 15:11:33 Functions: 0 0 -

          Line data    Source code
       1             : # TODO: We could work directly on the components of SparseMatrixCSC,
       2             : #       see spmap!
       3             : 
       4          26 : function spmap(f, A::SparseMatrixCSC; dropzeros::Bool=false)
       5          13 :     m, n = size(A)
       6          13 :     i, j, v = findnz(A)
       7          13 :     w = map(f, v)
       8          13 :     if dropzeros
       9           4 :         k = findall(isnonzero, w)
      10           4 :         sparse(i[k], j[k], w[k], m, n)
      11             :     else
      12           9 :         sparse(i, j, w, m, n)
      13             :     end
      14             : end
      15             : 
      16           8 : spmap(f, A::SparseT; kwargs...) = spmap(f, A'; kwargs...)'
      17             : 
      18             : """
      19             :     B = spmap(f, A[; dropzeros=false])
      20             : 
      21             : Get sparse matrix with values of `A` mapped by `f`.
      22             : 
      23             : If `A` is a sparse matrix, `spmap(A)` gives a sparse matrix and
      24             : `spmap(A')` gives an *adjoint* of a sparse matrix.
      25             : 
      26             : Unless `dropzeros=true`, the result will include structural zeros
      27             : (i.e., all values that mapped to zero).
      28             : 
      29             : """ spmap
      30             : 
      31             : 
      32             : """
      33             : 
      34             :     B = spfilter(predicate, A[; dropzeros=true])
      35             : 
      36             : Get sparse matrix with entries `predicate(A[i,j])`.
      37             : 
      38             : Calls [`spmap`](@ref) but with default setting `dropzeros=true`.
      39             : 
      40             : See also [`spmap`](@ref)
      41             : 
      42             : """
      43          12 : function spfilter(predicate, A::SparseOp; dropzeros::Bool=true)
      44             :     # TODO: alternative: SparseArrays.fkeep! if dropzeros
      45             : 
      46           6 :     ZERO = zero(eltype(A))
      47          60 :     spmap(v->predicate(v) ? v : ZERO, A, dropzeros=dropzeros)
      48             : end
      49             : 
      50             : """
      51             :     S = spones(A[; typ=eltype(A), dropzeros=false])
      52             : 
      53             : Get sparse matrix with nonzero entries replaced by `1`. Calls
      54             : [`spmap`](@ref). Note that any structural zeros are *not* replaced by
      55             : `1`.
      56             : 
      57             : See also [`spmap`](@ref)
      58             : """
      59          10 : function spones(A::SparseOp; typ::Type=eltype(A), dropzeros::Bool=false)
      60           5 :     ONE = one(typ)
      61             :     # default: keep structural zeros
      62     1404359 :     spmap(v->iszero(v) ? v : ONE, A, dropzeros=dropzeros)
      63             : end
      64             : 
      65             : """
      66             :     P = sppositive(A[; dropzeros=false])
      67             : 
      68             : Get sparse matrix with positive entries of `A`. Calls
      69             : [`spfilter`](@ref).
      70             : 
      71             : See also [`spmap`](@ref)
      72             : """
      73          12 : sppositive(A::SparseOp; dropzeros::Bool=false) =
      74             :     spfilter(ispositive, A, dropzeros=dropzeros)
      75             : 
      76             : #-----------------------------------------------------------------------------
      77             : 
      78        4923 : function _mapv!(f, v)
      79        4923 :     Threads.@threads for k in eachindex(v)
      80   345112907 :         @inbounds v[k] = f(v[k])
      81           0 :     end
      82             : 
      83             :     # @turbo inline = true unroll = 2 thread = true @. v = f(v)
      84             : 
      85        4923 :     v
      86             : end
      87             : 
      88        5042 : function _mapiv!(f, i, v)
      89        5042 :     @assert length(v) == length(i)
      90             : 
      91        5042 :     Threads.@threads for k in eachindex(v)
      92   353608186 :         @inbounds v[k] = f(i[k], v[k])
      93           0 :     end
      94             : 
      95             :     # @turbo inline = true unroll = 2 thread = true @. v = f(i, v)
      96             : 
      97        5042 :     v
      98             : end
      99             : 
     100             : """
     101             :     spmap!(f, A::SparseOp)
     102             : 
     103             : Apply `f(v)` to all nonzero values `v` in-place and return `A`.
     104             : 
     105             : See also [`spmapi!`](@ref), [`spmapj!`](@ref), [`spmapij!`](@ref), [`scale!`](@ref)
     106             : """
     107        4923 : function spmap!(f, A::SparseOp)
     108        4923 :     _mapv!(f, parent(A).nzval)
     109        4923 :     A
     110             : end
     111             : 
     112        5039 : function spmapi!(f, A::SparseMatrixCSC)
     113        5039 :     _mapiv!(f, A.rowval, A.nzval)
     114        5039 :     A
     115             : end
     116             : 
     117           3 : function spmapi!(f, A::SparseT)
     118       12129 :     spmapij!((i, _, v) -> f(i, v), A)
     119           3 :     A
     120             : end
     121             : 
     122             : """
     123             :     spmapi!(f, A::SparseOp) -> A
     124             : 
     125             : Apply `f(i, v)` to all nonzero values `v` providing the row index `i`
     126             : and return `A`.
     127             : 
     128             : !!! note
     129             :     This operation is more expensive on transposed matrices.
     130             : 
     131             : See also [`spmap!`](@ref), [`spmapj!`](@ref), [`spmapij!`](@ref), [`scale!`](@ref)
     132             : """ spmapi!
     133             : 
     134             : 
     135           3 : function spmapj!(f, A::SparseT)
     136           3 :     _mapiv!(f, parent(A).rowval, parent(A).nzval)
     137           3 :     A
     138             : end
     139             : 
     140        5493 : function spmapj!(f, A::SparseMatrixCSC)
     141   385485405 :     spmapij!((_, j, v) -> f(j, v), A)
     142        5493 :     A
     143             : end
     144             : 
     145             : """
     146             :     spmapj!(f, A::SparseOp) -> A
     147             : 
     148             : Apply `f(j, v)` to all nonzero values `v` providing the column index `j`
     149             : and return `A`.
     150             : 
     151             : !!! note
     152             :     This operation is less expensive on transposed matrices.
     153             : 
     154             : See also [`spmap!`](@ref), [`spmapi!`](@ref), [`spmapij!`](@ref), [`scale!`](@ref)
     155             : """ spmapj!
     156             : 
     157             : """
     158             :     spmapij!(f, A::SparseOp) -> A
     159             : 
     160             : Apply `f(i, j, v)` to all nonzero values `v` providing the row and
     161             : column indices `i, j` and return `A`.
     162             : 
     163             : See also [`spmapi!`](@ref), [`spmapj!`](@ref), [`spmapij!`](@ref), [`scale!`](@ref)
     164             : """
     165        5498 : function spmapij!(f, A::SparseOp)
     166        5498 :     M = parent(A)
     167        5498 :     _, n = size(M)
     168        5498 :     @assert length(M.colptr) == n+1
     169             : 
     170   385485810 :     g(::SparseMatrixCSC, i, j, v) = f(i, j, v)
     171       16168 :     g(::SparseT, i, j, v) = f(j, i, v)
     172             : 
     173        5498 :     for j in 1:n, k in M.colptr[j]:(M.colptr[j+1]-1)
     174   385486877 :         i = M.rowval[k]
     175   385486877 :         v = M.nzval[k]
     176             : 
     177   385486877 :         M.nzval[k] = g(A, i, j, v)
     178   390976487 :     end
     179             : 
     180        5498 :     A
     181             : end
     182             : 
     183        4921 : function scale!(A::SparseOp, α)
     184   345112591 :     spmap!(v -> (α * v), A)
     185        4921 :     A
     186             : end
     187             : 
     188             : """
     189             :     scalerows!(A::SpaceOp, w[, α=1])
     190             : 
     191             : Scale rows of `A` in-place as for `A = A * (α * Diagonal(w))` and
     192             : return `A`.
     193             : 
     194             : See also [`scale!`](@ref), [`scalecols`](@ref)
     195             : """
     196        5040 : function scalerows!(A::SparseOp, w::AbstractVector, α=eltype(A)(1))
     197        5040 :     @assert length(w) == size(A, 1)
     198             : 
     199   353607882 :     spmapi!((i, v) -> (α * v * w[i]), A)
     200             : end
     201             : 
     202             : # #
     203             : # function scalerows!(A::SparseMatrixCSC, w::AbstractVector, α=eltype(A)(1))
     204             : #     @assert length(w) == size(A, 1)
     205             : 
     206             : #     W = Vector{eltype(A)}(undef, nnz(A))
     207             : #     for i in eachindex(A.nzval)
     208             : #         W[i] = w[A.rowval[i]] * α
     209             : #     end
     210             : 
     211             : #     A.nzval .*= W
     212             : 
     213             : #     # for i in eachindex(A.nzval)
     214             : #     #     A.nzval[i] *= α * w[A.rowval[i]]
     215             : #     # end
     216             : 
     217             : #     A
     218             : # end
     219             : # #
     220             : 
     221             : """
     222             :     scalecols!(A::SpaceOp, w[, α=1])
     223             : 
     224             : Scale columns of `A` in-place as for `A = α * Diagonal(w) * A` and
     225             : return `A`.
     226             : 
     227             : See also [`scale!`](@ref), [`scalerows`](@ref)
     228             : """
     229        5494 : function scalecols!(A::SparseOp, w::AbstractVector{T}, α=eltype(A)(1)) where {T}
     230        5494 :     @assert length(w) == size(A, 2)
     231             : 
     232   385485810 :     spmapj!((j, v) -> α * v * w[j], A)
     233             : end
     234             : 
     235        2516 : scale!(D::Diagonal, A::SparseOp, α=eltype(A)(1)) = scalerows!(A, parent(D), α)
     236             : 
     237        8237 : scale!(A::SparseOp, D::Diagonal, α=eltype(A)(1)) = scalecols!(A, parent(D), α)
     238             : 
     239           2 : scale!(::UniformScaling, A::SparseOp, α) = scale!(A, α)
     240             : 
     241           2 : scale!(A::SparseOp, ::UniformScaling, α) = scale!(A, α)
     242             : 
     243             : """
     244             : In-place methods for `A = A * α`
     245             : 
     246             :     scale!(A, α)
     247             :     scale!(I, A, α)
     248             :     scale!(A, I, α)
     249             : 
     250             : In-place methods for `A = A * (α * Diagonal(w))`, i.e., scale rows
     251             : 
     252             :     scalerows!(A, w[, α=1])
     253             :     scale!(A, Diagonal(w)[, α=1])
     254             : 
     255             : In-place methods for `A = α * Diagonal(w) * A`, i.e., scale rows
     256             : 
     257             :     scalecols!(A, w[, α=1])
     258             :     scale!(Diagonal(w), A, [, α=1])
     259             : 
     260             : Scale rows or columns of sparse operator `A` in-place and
     261             : return `A`.
     262             : 
     263             : !!! note
     264             :     `A::SparseOp` can be a sparse matrix or a transposed matrix.
     265             :      Mind different cost: scaling rows (or columns of `A'`) is
     266             :      less expensive than scaling columns (or rows of `A'`).
     267             : 
     268             : !!! note
     269             :     All methods return `A`, i.e., the object that was modified.
     270             : 
     271             : See also [`scalerows`](@ref), [`scalecols`](@ref), [`spmap!`](@ref),
     272             : [`spmapi!`](@ref), [`spmapj!`](@ref)
     273             : """ scale!

Generated by: LCOV version 1.16