@@ -1398,31 +1398,19 @@ end
1398
1398
1399
1399
sparse (S:: UniformScaling , m:: Integer , n:: Integer = m) = speye_scaled (S. λ, m, n)
1400
1400
1401
- # # Unary arithmetic and boolean operators
1402
1401
1403
- """
1404
- Helper macro for the unary broadcast definitions below. Takes parent method `fp` and a set
1405
- of desired child methods `fcs`, and builds an expression defining each of the child methods
1406
- such that `broadcast(::typeof(fc), A::SparseMatrixCSC) = fp(fc, A)`.
1407
- """
1408
- macro _enumerate_childmethods (fp, fcs... )
1409
- fcexps = Expr (:block )
1410
- for fc in fcs
1411
- push! (fcexps. args, :( $ (esc (:broadcast ))(:: typeof ($ (esc (fc))), A:: SparseMatrixCSC ) = $ (esc (fp))($ (esc (fc)), A) ) )
1412
- end
1413
- return fcexps
1414
- end
1402
+ # # Broadcast operations involving a single sparse matrix and possibly broadcast scalars
1415
1403
1416
- # Operations that map zeros to zeros and may map nonzeros to zeros, yielding a sparse matrix
1417
- """
1418
- Takes unary function `f` that maps zeros to zeros and may map nonzeros to zeros, and returns
1419
- a new `SparseMatrixCSC{TiA,TvB}` `B` generated by applying `f` to each nonzero entry in
1420
- `A` and retaining only the resulting nonzeros.
1421
- "" "
1422
- function _broadcast_unary_nz2z_z2z_T {TvA,TiA,TvB } (f:: Function , A:: SparseMatrixCSC{TvA,TiA} , :: Type{TvB} )
1423
- Bcolptr = Array {TiA} ( A. n + 1 )
1424
- Browval = Array {TiA} ( nnz (A))
1425
- Bnzval = Array {TvB} ( nnz (A))
1404
+ function broadcast {Tf} (f :: Tf , A :: SparseMatrixCSC )
1405
+ fofzero = f ( zero ( eltype (A)))
1406
+ fpreszero = fofzero == zero (fofzero)
1407
+ return fpreszero ? _broadcast_zeropres (f, A) : _broadcast_notzeropres (f, fofzero, A)
1408
+ end
1409
+ " Returns a `SparseMatrixCSC` storing only the nonzero entries of `broadcast(f, Matrix(A))`. "
1410
+ function _broadcast_zeropres {Tf } (f:: Tf , A:: SparseMatrixCSC )
1411
+ Bcolptr = similar (A . colptr, A. n + 1 )
1412
+ Browval = similar (A . rowval, nnz (A))
1413
+ Bnzval = similar (A . nzval, Base . Broadcast . promote_eltype_op (f, A), nnz (A))
1426
1414
Bk = 1
1427
1415
@inbounds for j in 1 : A. n
1428
1416
Bcolptr[j] = Bk
@@ -1440,69 +1428,51 @@ function _broadcast_unary_nz2z_z2z_T{TvA,TiA,TvB}(f::Function, A::SparseMatrixCS
1440
1428
resize! (Bnzval, Bk - 1 )
1441
1429
return SparseMatrixCSC (A. m, A. n, Bcolptr, Browval, Bnzval)
1442
1430
end
1443
- function _broadcast_unary_nz2z_z2z {Tv} (f:: Function , A:: SparseMatrixCSC{Tv} )
1444
- _broadcast_unary_nz2z_z2z_T (f, A, Tv)
1445
- end
1446
- @_enumerate_childmethods (_broadcast_unary_nz2z_z2z,
1447
- sin, sinh, sind, asin, asinh, asind,
1448
- tan, tanh, tand, atan, atanh, atand,
1449
- sinpi, cosc, ceil, floor, trunc, round)
1450
- broadcast (:: typeof (real), A:: SparseMatrixCSC ) = copy (A)
1451
- broadcast {Tv,Ti} (:: typeof (imag), A:: SparseMatrixCSC{Tv,Ti} ) = spzeros (Tv, Ti, A. m, A. n)
1452
- broadcast {TTv} (:: typeof (real), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2z_z2z_T (real, A, TTv)
1453
- broadcast {TTv} (:: typeof (imag), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2z_z2z_T (imag, A, TTv)
1454
- ceil {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (ceil, A, To)
1455
- floor {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (floor, A, To)
1456
- trunc {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (trunc, A, To)
1457
- round {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (round, A, To)
1458
-
1459
- # Operations that map zeros to zeros and map nonzeros to nonzeros, yielding a sparse matrix
1460
- """
1461
- Takes unary function `f` that maps zeros to zeros and nonzeros to nonzeros, and returns a
1462
- new `SparseMatrixCSC{TiA,TvB}` `B` generated by applying `f` to each nonzero entry in `A`.
1463
- """
1464
- function _broadcast_unary_nz2nz_z2z {TvA,TiA,Tf<:Function} (f:: Tf , A:: SparseMatrixCSC{TvA,TiA} )
1465
- Bcolptr = Vector {TiA} (A. n + 1 )
1466
- Browval = Vector {TiA} (nnz (A))
1467
- copy! (Bcolptr, 1 , A. colptr, 1 , A. n + 1 )
1468
- copy! (Browval, 1 , A. rowval, 1 , nnz (A))
1469
- Bnzval = broadcast (f, A. nzval)
1470
- resize! (Bnzval, nnz (A))
1471
- return SparseMatrixCSC (A. m, A. n, Bcolptr, Browval, Bnzval)
1472
- end
1473
- @_enumerate_childmethods (_broadcast_unary_nz2nz_z2z,
1474
- log1p, expm1, abs, abs2, conj)
1475
- function conj! (A:: SparseMatrixCSC )
1476
- @inbounds @simd for k in 1 : nnz (A)
1477
- A. nzval[k] = conj (A. nzval[k])
1478
- end
1479
- return A
1480
- end
1481
-
1482
- # Operations that map both zeros and nonzeros to zeros, yielding a dense matrix
1483
1431
"""
1484
- Takes unary function `f` that maps both zeros and nonzeros to nonzeros, constructs a new
1485
- `Matrix{TvB}` `B`, populates all entries of `B` with the result of a single `f(one(zero(Tv)))`
1486
- call, and then, for each stored entry in `A`, calls `f` on the entry's value and stores the
1487
- result in the corresponding location in `B`.
1432
+ Returns a (dense) `SparseMatrixCSC` with `fillvalue` stored in place of each unstored
1433
+ entry in `A` and `f(A[i,j])` stored in place of each stored entry `A[i,j]` in `A`.
1488
1434
"""
1489
- function _broadcast_unary_nz2nz_z2nz {Tv} (f:: Function , A:: SparseMatrixCSC{Tv} )
1490
- B = fill (f (zero (Tv)), size (A))
1491
- @inbounds for j in 1 : A. n
1492
- for k in nzrange (A, j)
1493
- i = A. rowval[k]
1494
- x = A. nzval[k]
1495
- B[i,j] = f (x)
1496
- end
1435
+ function _broadcast_notzeropres {Tf} (f:: Tf , fillvalue, A:: SparseMatrixCSC )
1436
+ nnzB = A. m * A. n
1437
+ # Build structure
1438
+ Bcolptr = similar (A. colptr, A. n + 1 )
1439
+ copy! (Bcolptr, 1 : A. m: (nnzB + 1 ))
1440
+ Browval = similar (A. rowval, nnzB)
1441
+ for k in 1 : A. m: (nnzB - A. m + 1 )
1442
+ copy! (Browval, k, 1 : A. m)
1443
+ end
1444
+ # Populate values
1445
+ Bnzval = fill (fillvalue, nnzB)
1446
+ @inbounds for (j, jo) in zip (1 : A. n, 0 : A. m: (nnzB - 1 )), k in nzrange (A, j)
1447
+ Bnzval[jo + A. rowval[k]] = f (A. nzval[k])
1497
1448
end
1498
- return B
1449
+ # NOTE: Combining the fill call into the loop above to avoid multiple sweeps over /
1450
+ # nonsequential access of Bnzval does not appear to improve performance
1451
+ return SparseMatrixCSC (A. m, A. n, Bcolptr, Browval, Bnzval)
1499
1452
end
1500
- @_enumerate_childmethods (_broadcast_unary_nz2nz_z2nz,
1501
- log, log2, log10, exp, exp2, exp10, sinc, cospi,
1502
- cos, cosh, cosd, acos, acosd,
1503
- cot, coth, cotd, acot, acotd,
1504
- sec, sech, secd, asech,
1505
- csc, csch, cscd, acsch)
1453
+
1454
+ # Cover common broadcast operations involving a single sparse matrix and one or more
1455
+ # broadcast scalars.
1456
+ #
1457
+ # TODO : The minimal snippet below is not satisfying: A better solution would achieve
1458
+ # the same for (1) all broadcast scalar types (Base.Broadcast.containertype(x) == Any?) and
1459
+ # (2) any combination (number, order, type mixture) of broadcast scalars.
1460
+ #
1461
+ broadcast {Tf} (f:: Tf , x:: Union{Number,Bool} , A:: SparseMatrixCSC ) = broadcast (y -> f (x, y), A)
1462
+ broadcast {Tf} (f:: Tf , A:: SparseMatrixCSC , y:: Union{Number,Bool} ) = broadcast (x -> f (x, y), A)
1463
+ # NOTE: The following two method definitions work around #19096. These definitions should
1464
+ # be folded into the two preceding definitions on resolution of #19096.
1465
+ broadcast {Tf,T} (f:: Tf , :: Type{T} , A:: SparseMatrixCSC ) = broadcast (y -> f (T, y), A)
1466
+ broadcast {Tf,T} (f:: Tf , A:: SparseMatrixCSC , :: Type{T} ) = broadcast (x -> f (x, T), A)
1467
+
1468
+ # TODO : The following definitions should be deprecated.
1469
+ ceil {To} (:: Type{To} , A:: SparseMatrixCSC ) = ceil .(To, A)
1470
+ floor {To} (:: Type{To} , A:: SparseMatrixCSC ) = floor .(To, A)
1471
+ trunc {To} (:: Type{To} , A:: SparseMatrixCSC ) = trunc .(To, A)
1472
+ round {To} (:: Type{To} , A:: SparseMatrixCSC ) = round .(To, A)
1473
+
1474
+ # TODO : More appropriate location?
1475
+ conj! (A:: SparseMatrixCSC ) = (broadcast! (conj, A. nzval, A. nzval); A)
1506
1476
1507
1477
1508
1478
# # Broadcasting kernels specialized for returning a SparseMatrixCSC
0 commit comments