@@ -1305,134 +1305,118 @@ end
1305
1305
1306
1306
# # Unary arithmetic and boolean operators
1307
1307
1308
- macro _unary_op_nz2z_z2z (op,A,Tv,Ti)
1309
- esc (quote
1310
- nfilledA = nnz ($ A)
1311
- colptrB = Array {$Ti} ($ A. n+ 1 )
1312
- rowvalB = Array {$Ti} (nfilledA)
1313
- nzvalB = Array {$Tv} (nfilledA)
1314
-
1315
- nzvalA = $ A. nzval
1316
- colptrA = $ A. colptr
1317
- rowvalA = $ A. rowval
1318
-
1319
- k = 0 # number of additional zeros introduced by op(A)
1320
- @inbounds for i = 1 : $ A. n
1321
- colptrB[i] = colptrA[i] - k
1322
- for j = colptrA[i] : colptrA[i+ 1 ]- 1
1323
- opAj = $ (op)(nzvalA[j])
1324
- if opAj == 0
1325
- k += 1
1326
- else
1327
- rowvalB[j - k] = rowvalA[j]
1328
- nzvalB[j - k] = opAj
1329
- end
1330
- end
1331
- end
1332
- colptrB[end ] = $ A. colptr[end ] - k
1333
- deleteat! (rowvalB, colptrB[end ]: nfilledA)
1334
- deleteat! (nzvalB, colptrB[end ]: nfilledA)
1335
- return SparseMatrixCSC ($ A. m, $ A. n, colptrB, rowvalB, nzvalB)
1336
- end ) # quote
1337
- end
1338
-
1339
- # Operations that may map nonzeros to zero, and zero to zero
1340
- # Result is sparse
1341
- for op in (:ceil , :floor , :trunc , :round ,
1342
- :sin , :tan , :asin , :atan ,
1343
- :sinh , :tanh , :asinh , :atanh ,
1344
- :sinpi , :cosc ,
1345
- :sind , :tand , :asind , :atand )
1346
- @eval begin
1347
- $ (op){Tv,Ti}(A:: SparseMatrixCSC{Tv,Ti} ) = @_unary_op_nz2z_z2z ($ op,A,Tv,Ti)
1348
- end # quote
1349
- end # macro
1350
-
1351
- for op in (:real , :imag )
1352
- @eval begin
1353
- ($ op){Tv<: Complex ,Ti}(A:: SparseMatrixCSC{Tv,Ti} ) = @_unary_op_nz2z_z2z ($ op,A,Tv. parameters[1 ],Ti)
1354
- end # quote
1355
- end # macro
1356
- real {Tv<:Number,Ti} (A:: SparseMatrixCSC{Tv,Ti} ) = copy (A)
1357
- imag {Tv<:Number,Ti} (A:: SparseMatrixCSC{Tv,Ti} ) = spzeros (Tv, Ti, A. m, A. n)
1358
-
1359
- for op in (:ceil , :floor , :trunc , :round )
1360
- @eval begin
1361
- ($ op){T,Tv,Ti}(:: Type{T} ,A:: SparseMatrixCSC{Tv,Ti} ) = @_unary_op_nz2z_z2z ($ op,A,T,Ti)
1362
- end # quote
1363
- end # macro
1364
-
1365
-
1366
- # Operations that map nonzeros to nonzeros, and zeros to zeros
1367
- # Result is sparse
1368
- for op in (:- , :log1p , :expm1 )
1369
- @eval begin
1370
-
1371
- function ($ op)(A:: SparseMatrixCSC )
1372
- B = similar (A)
1373
- nzvalB = B. nzval
1374
- nzvalA = A. nzval
1375
- @simd for i= 1 : length (nzvalB)
1376
- @inbounds nzvalB[i] = ($ op)(nzvalA[i])
1377
- end
1378
- return B
1379
- end
1380
-
1381
- end
1382
- end
1383
-
1384
- function abs {Tv<:Complex,Ti} (A:: SparseMatrixCSC{Tv,Ti} )
1385
- T = Tv. parameters[1 ]
1386
- (T <: Integer ) && (T = (T <: BigInt ) ? BigFloat : Float64)
1387
- @_unary_op_nz2z_z2z (abs,A,T,Ti)
1388
- end
1389
- abs2 {Tv<:Complex,Ti} (A:: SparseMatrixCSC{Tv,Ti} ) = @_unary_op_nz2z_z2z (abs2,A,Tv. parameters[1 ],Ti)
1390
- for op in (:abs , :abs2 )
1391
- @eval begin
1392
- function ($ op){Tv<: Number ,Ti}(A:: SparseMatrixCSC{Tv,Ti} )
1393
- B = similar (A)
1394
- nzvalB = B. nzval
1395
- nzvalA = A. nzval
1396
- @simd for i= 1 : length (nzvalB)
1397
- @inbounds nzvalB[i] = ($ op)(nzvalA[i])
1308
+ """
1309
+ Helper macro for the unary broadcast definitions below. Takes parent method `fp` and a set
1310
+ of desired child methods `fcs`, and builds an expression defining each of the child methods
1311
+ such that `broadcast(::typeof(fc), A::SparseMatrixCSC) = fp(fc, A)`.
1312
+ """
1313
+ macro _enumerate_childmethods (fp, fcs... )
1314
+ fcexps = Expr (:block )
1315
+ for fc in fcs
1316
+ push! (fcexps. args, :( broadcast (:: typeof ($ (esc (fc))), A:: SparseMatrixCSC ) = $ (esc (fp))($ (esc (fc)), A) ) )
1317
+ end
1318
+ return fcexps
1319
+ end
1320
+
1321
+ # Operations that map zeros to zeros and may map nonzeros to zeros, yielding a sparse matrix
1322
+ """
1323
+ Takes unary function `f` that maps zeros to zeros and may map nonzeros to zeros, and returns
1324
+ a new `SparseMatrixCSC{TiA,TvB}` `B` generated by applying `f` to each nonzero entry in
1325
+ `A` and retaining only the resulting nonzeros.
1326
+ """
1327
+ function _broadcast_unary_nz2z_z2z_T {TvA,TiA,TvB} (f:: Function , A:: SparseMatrixCSC{TvA,TiA} , :: Type{TvB} )
1328
+ Bcolptr = Array {TiA} (A. n + 1 )
1329
+ Browval = Array {TiA} (nnz (A))
1330
+ Bnzval = Array {TvB} (nnz (A))
1331
+ Bk = 1
1332
+ @inbounds for j in 1 : A. n
1333
+ Bcolptr[j] = Bk
1334
+ for Ak in nzrange (A, j)
1335
+ x = f (A. nzval[Ak])
1336
+ if x != 0
1337
+ Browval[Bk] = A. rowval[Ak]
1338
+ Bnzval[Bk] = x
1339
+ Bk += 1
1398
1340
end
1399
- return B
1400
1341
end
1401
1342
end
1402
- end
1403
-
1343
+ Bcolptr[A. n + 1 ] = Bk
1344
+ resize! (Browval, Bk - 1 )
1345
+ resize! (Bnzval, Bk - 1 )
1346
+ return SparseMatrixCSC (A. m, A. n, Bcolptr, Browval, Bnzval)
1347
+ end
1348
+ function _broadcast_unary_nz2z_z2z {Tv} (f:: Function , A:: SparseMatrixCSC{Tv} )
1349
+ _broadcast_unary_nz2z_z2z_T (f, A, Tv)
1350
+ end
1351
+ @_enumerate_childmethods (_broadcast_unary_nz2z_z2z,
1352
+ sin, sinh, sind, asin, asinh, asind,
1353
+ tan, tanh, tand, atan, atanh, atand,
1354
+ sinpi, cosc, ceil, floor, trunc, round)
1355
+ broadcast (:: typeof (real), A:: SparseMatrixCSC ) = copy (A)
1356
+ broadcast {Tv,Ti} (:: typeof (imag), A:: SparseMatrixCSC{Tv,Ti} ) = spzeros (Tv, Ti, A. m, A. n)
1357
+ broadcast {TTv} (:: typeof (real), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2z_z2z_T (real, A, TTv)
1358
+ broadcast {TTv} (:: typeof (imag), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2z_z2z_T (imag, A, TTv)
1359
+ ceil {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (ceil, A, To)
1360
+ floor {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (floor, A, To)
1361
+ trunc {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (trunc, A, To)
1362
+ round {To} (:: Type{To} , A:: SparseMatrixCSC ) = _broadcast_unary_nz2z_z2z_T (round, A, To)
1363
+
1364
+ # Operations that map zeros to zeros and map nonzeros to nonzeros, yielding a sparse matrix
1365
+ """
1366
+ Takes unary function `f` that maps zeros to zeros and nonzeros to nonzeros, and returns a
1367
+ new `SparseMatrixCSC{TiA,TvB}` `B` generated by applying `f` to each nonzero entry in `A`.
1368
+ """
1369
+ function _broadcast_unary_nz2nz_z2z_T {TvA,TiA,TvB} (f:: Function , A:: SparseMatrixCSC{TvA,TiA} , :: Type{TvB} )
1370
+ Bcolptr = Vector {TiA} (A. n + 1 )
1371
+ Browval = Vector {TiA} (nnz (A))
1372
+ Bnzval = Vector {TvB} (nnz (A))
1373
+ copy! (Bcolptr, 1 , A. colptr, 1 , A. n + 1 )
1374
+ copy! (Browval, 1 , A. rowval, 1 , nnz (A))
1375
+ @inbounds @simd for k in 1 : nnz (A)
1376
+ Bnzval[k] = f (A. nzval[k])
1377
+ end
1378
+ return SparseMatrixCSC (A. m, A. n, Bcolptr, Browval, Bnzval)
1379
+ end
1380
+ function _broadcast_unary_nz2nz_z2z {Tv} (f:: Function , A:: SparseMatrixCSC{Tv} )
1381
+ _broadcast_unary_nz2nz_z2z_T (f, A, Tv)
1382
+ end
1383
+ @_enumerate_childmethods (_broadcast_unary_nz2nz_z2z,
1384
+ log1p, expm1, abs, abs2, conj)
1385
+ broadcast {TTv} (:: typeof (abs2), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2nz_z2z_T (abs2, A, TTv)
1386
+ broadcast {TTv} (:: typeof (abs), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2nz_z2z_T (abs, A, TTv)
1387
+ broadcast {TTv<:Integer} (:: typeof (abs), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2nz_z2z_T (abs, A, Float64)
1388
+ broadcast {TTv<:BigInt} (:: typeof (abs), A:: SparseMatrixCSC{Complex{TTv}} ) = _broadcast_unary_nz2nz_z2z_T (abs, A, BigFloat)
1404
1389
function conj! (A:: SparseMatrixCSC )
1405
- nzvalA = A. nzval
1406
- @simd for i= 1 : length (nzvalA)
1407
- @inbounds nzvalA[i] = conj (nzvalA[i])
1390
+ @inbounds @simd for k in 1 : nnz (A)
1391
+ A. nzval[k] = conj (A. nzval[k])
1408
1392
end
1409
1393
return A
1410
1394
end
1411
1395
1412
- conj (A:: SparseMatrixCSC ) = conj! (copy (A))
1413
-
1414
- # Operations that map nonzeros to nonzeros, and zeros to nonzeros
1415
- # Result is dense
1416
- for op in (:cos , :cosh , :acos , :sec , :csc , :cot , :acot , :sech ,
1417
- :csch , :coth , :asech , :acsch , :cospi , :sinc , :cosd ,
1418
- :cotd , :cscd , :secd , :acosd , :acotd , :log , :log2 , :log10 ,
1419
- :exp , :exp2 , :exp10 )
1420
- @eval begin
1421
-
1422
- function ($ op){Tv}(A:: SparseMatrixCSC{Tv} )
1423
- B = fill ($ (op)(zero (Tv)), size (A))
1424
- @inbounds for col = 1 : A. n
1425
- for j = A. colptr[col] : A. colptr[col+ 1 ]- 1
1426
- row = A. rowval[j]
1427
- nz = A. nzval[j]
1428
- B[row,col] = $ (op)(nz)
1429
- end
1430
- end
1431
- return B
1396
+ # Operations that map both zeros and nonzeros to zeros, yielding a dense matrix
1397
+ """
1398
+ Takes unary function `f` that maps both zeros and nonzeros to nonzeros, constructs a new
1399
+ `Matrix{TvB}` `B`, populates all entries of `B` with the result of a single `f(one(zero(Tv)))`
1400
+ call, and then, for each stored entry in `A`, calls `f` on the entry's value and stores the
1401
+ result in the corresponding location in `B`.
1402
+ """
1403
+ function _broadcast_unary_nz2nz_z2nz {Tv} (f:: Function , A:: SparseMatrixCSC{Tv} )
1404
+ B = fill (f (zero (Tv)), size (A))
1405
+ @inbounds for j in 1 : A. n
1406
+ for k in nzrange (A, j)
1407
+ i = A. rowval[k]
1408
+ x = A. nzval[k]
1409
+ B[i,j] = f (x)
1432
1410
end
1433
-
1434
1411
end
1412
+ return B
1435
1413
end
1414
+ @_enumerate_childmethods (_broadcast_unary_nz2nz_z2nz,
1415
+ log, log2, log10, exp, exp2, exp10, sinc, cospi,
1416
+ cos, cosh, cosd, acos, acosd,
1417
+ cot, coth, cotd, acot, acotd,
1418
+ sec, sech, secd, asech,
1419
+ csc, csch, cscd, acsch)
1436
1420
1437
1421
1438
1422
# # Broadcasting kernels specialized for returning a SparseMatrixCSC
@@ -1734,7 +1718,7 @@ end # macro
1734
1718
(.^ )(A:: SparseMatrixCSC , B:: Number ) =
1735
1719
B== 0 ? sparse (ones (typeof (one (eltype (A)).^ B), A. m, A. n)) :
1736
1720
SparseMatrixCSC (A. m, A. n, copy (A. colptr), copy (A. rowval), A. nzval .^ B)
1737
- (.^ )(:: Irrational{:e} , B:: SparseMatrixCSC ) = exp (B)
1721
+ (.^ )(:: Irrational{:e} , B:: SparseMatrixCSC ) = exp . (B)
1738
1722
(.^ )(A:: Number , B:: SparseMatrixCSC ) = (.^ )(A, full (B))
1739
1723
(.^ )(A:: SparseMatrixCSC , B:: Array ) = (.^ )(full (A), B)
1740
1724
(.^ )(A:: Array , B:: SparseMatrixCSC ) = (.^ )(A, full (B))
0 commit comments