@@ -2327,19 +2327,16 @@ function setindex!(A::SparseMatrixCSC{Tv,Ti}, v::Tv, i::Ti, j::Ti) where Tv wher
2327
2327
return A
2328
2328
end
2329
2329
2330
- setindex! (A:: SparseMatrixCSC , v:: AbstractMatrix , i:: Integer , J:: AbstractVector{<:Integer} ) = setindex! (A, v, [i], J)
2331
- setindex! (A:: SparseMatrixCSC , v:: AbstractMatrix , I:: AbstractVector{<:Integer} , j:: Integer ) = setindex! (A, v, I, [j])
2332
-
2333
- setindex! (A:: SparseMatrixCSC , x:: Number , i:: Integer , J:: AbstractVector{<:Integer} ) = setindex! (A, x, [i], J)
2334
- setindex! (A:: SparseMatrixCSC , x:: Number , I:: AbstractVector{<:Integer} , j:: Integer ) = setindex! (A, x, I, [j])
2330
+ setindex! (A:: SparseMatrixCSC , x, i:: Integer , J:: AbstractVector{<:Integer} ) = setindex! (A, x, [i], J)
2331
+ setindex! (A:: SparseMatrixCSC , x, I:: AbstractVector{<:Integer} , j:: Integer ) = setindex! (A, x, I, [j])
2335
2332
2336
2333
# Colon translation
2337
2334
setindex! (A:: SparseMatrixCSC , x, :: Colon ) = setindex! (A, x, 1 : length (A))
2338
2335
setindex! (A:: SparseMatrixCSC , x, :: Colon , :: Colon ) = setindex! (A, x, 1 : size (A, 1 ), 1 : size (A,2 ))
2339
2336
setindex! (A:: SparseMatrixCSC , x, :: Colon , j:: Union{Integer, AbstractVector} ) = setindex! (A, x, 1 : size (A, 1 ), j)
2340
2337
setindex! (A:: SparseMatrixCSC , x, i:: Union{Integer, AbstractVector} , :: Colon ) = setindex! (A, x, i, 1 : size (A, 2 ))
2341
2338
2342
- function setindex! (A:: SparseMatrixCSC{Tv} , x:: Number ,
2339
+ function setindex! (A:: SparseMatrixCSC{Tv} , x,
2343
2340
I:: AbstractVector{<:Integer} , J:: AbstractVector{<:Integer} ) where Tv
2344
2341
if isempty (I) || isempty (J); return A; end
2345
2342
# lt=≤ to check for strict sorting
@@ -2500,155 +2497,6 @@ function _spsetnz_setindex!(A::SparseMatrixCSC{Tv}, x::Tv,
2500
2497
return A
2501
2498
end
2502
2499
2503
- setindex! (A:: SparseMatrixCSC{Tv,Ti} , S:: Matrix , I:: AbstractVector{T} , J:: AbstractVector{T} ) where {Tv,Ti,T<: Integer } =
2504
- setindex! (A, convert (SparseMatrixCSC{Tv,Ti}, S), I, J)
2505
-
2506
- setindex! (A:: SparseMatrixCSC , v:: AbstractVector , I:: AbstractVector{<:Integer} , j:: Integer ) = setindex! (A, v, I, [j])
2507
- setindex! (A:: SparseMatrixCSC , v:: AbstractVector , i:: Integer , J:: AbstractVector{<:Integer} ) = setindex! (A, v, [i], J)
2508
- setindex! (A:: SparseMatrixCSC , v:: AbstractVector , I:: AbstractVector{T} , J:: AbstractVector{T} ) where {T<: Integer } =
2509
- setindex! (A, reshape (v, length (I), length (J)), I, J)
2510
-
2511
- # A[I,J] = B
2512
- function setindex! (A:: SparseMatrixCSC{Tv,Ti} , B:: SparseMatrixCSC{Tv,Ti} , I:: AbstractVector{T} , J:: AbstractVector{T} ) where {Tv,Ti,T<: Integer }
2513
- if size (B,1 ) != length (I) || size (B,2 ) != length (J)
2514
- throw (DimensionMismatch (" " ))
2515
- end
2516
-
2517
- issortedI = issorted (I)
2518
- issortedJ = issorted (J)
2519
-
2520
- if ! issortedI && ! issortedJ
2521
- pI = sortperm (I); @inbounds I = I[pI]
2522
- pJ = sortperm (J); @inbounds J = J[pJ]
2523
- B = B[pI, pJ]
2524
- elseif ! issortedI
2525
- pI = sortperm (I); @inbounds I = I[pI]
2526
- B = B[pI,:]
2527
- elseif ! issortedJ
2528
- pJ = sortperm (J); @inbounds J = J[pJ]
2529
- B = B[:, pJ]
2530
- end
2531
-
2532
- m, n = size (A)
2533
- mB, nB = size (B)
2534
-
2535
- if (! isempty (I) && (I[1 ] < 1 || I[end ] > m)) || (! isempty (J) && (J[1 ] < 1 || J[end ] > n))
2536
- throw (BoundsError (A, (I, J)))
2537
- end
2538
-
2539
- if isempty (I) || isempty (J)
2540
- return A
2541
- end
2542
-
2543
- nI = length (I)
2544
- nJ = length (J)
2545
-
2546
- colptrA = A. colptr; rowvalA = A. rowval; nzvalA = A. nzval
2547
- colptrB = B. colptr; rowvalB = B. rowval; nzvalB = B. nzval
2548
-
2549
- nnzS = nnz (A) + nnz (B)
2550
-
2551
- colptrS = copy (A. colptr)
2552
- rowvalS = copy (A. rowval)
2553
- nzvalS = copy (A. nzval)
2554
-
2555
- resize! (rowvalA, nnzS)
2556
- resize! (nzvalA, nnzS)
2557
-
2558
- colB = 1
2559
- asgn_col = J[colB]
2560
-
2561
- I_asgn = falses (m)
2562
- I_asgn[I] = true
2563
-
2564
- ptrS = 1
2565
-
2566
- @inbounds for col = 1 : n
2567
-
2568
- # Copy column of A if it is not being assigned into
2569
- if colB > nJ || col != J[colB]
2570
- colptrA[col+ 1 ] = colptrA[col] + (colptrS[col+ 1 ]- colptrS[col])
2571
-
2572
- for k = colptrS[col]: colptrS[col+ 1 ]- 1
2573
- rowvalA[ptrS] = rowvalS[k]
2574
- nzvalA[ptrS] = nzvalS[k]
2575
- ptrS += 1
2576
- end
2577
- continue
2578
- end
2579
-
2580
- ptrA:: Int = colptrS[col]
2581
- stopA:: Int = colptrS[col+ 1 ]
2582
- ptrB:: Int = colptrB[colB]
2583
- stopB:: Int = colptrB[colB+ 1 ]
2584
-
2585
- while ptrA < stopA && ptrB < stopB
2586
- rowA = rowvalS[ptrA]
2587
- rowB = I[rowvalB[ptrB]]
2588
- if rowA < rowB
2589
- rowvalA[ptrS] = rowA
2590
- nzvalA[ptrS] = I_asgn[rowA] ? zero (Tv) : nzvalS[ptrA]
2591
- ptrS += 1
2592
- ptrA += 1
2593
- elseif rowB < rowA
2594
- if nzvalB[ptrB] != zero (Tv)
2595
- rowvalA[ptrS] = rowB
2596
- nzvalA[ptrS] = nzvalB[ptrB]
2597
- ptrS += 1
2598
- end
2599
- ptrB += 1
2600
- else
2601
- rowvalA[ptrS] = rowB
2602
- nzvalA[ptrS] = nzvalB[ptrB]
2603
- ptrS += 1
2604
- ptrB += 1
2605
- ptrA += 1
2606
- end
2607
- end
2608
-
2609
- while ptrA < stopA
2610
- rowA = rowvalS[ptrA]
2611
- rowvalA[ptrS] = rowA
2612
- nzvalA[ptrS] = I_asgn[rowA] ? zero (Tv) : nzvalS[ptrA]
2613
- ptrS += 1
2614
- ptrA += 1
2615
- end
2616
-
2617
- while ptrB < stopB
2618
- rowB = I[rowvalB[ptrB]]
2619
- if nzvalB[ptrB] != zero (Tv)
2620
- rowvalA[ptrS] = rowB
2621
- nzvalA[ptrS] = nzvalB[ptrB]
2622
- ptrS += 1
2623
- end
2624
- ptrB += 1
2625
- end
2626
-
2627
- colptrA[col+ 1 ] = ptrS
2628
- colB += 1
2629
- end
2630
-
2631
- deleteat! (rowvalA, colptrA[end ]: length (rowvalA))
2632
- deleteat! (nzvalA, colptrA[end ]: length (nzvalA))
2633
-
2634
- return A
2635
- end
2636
-
2637
- # Logical setindex!
2638
-
2639
- setindex! (A:: SparseMatrixCSC , x:: Matrix , I:: Integer , J:: AbstractVector{Bool} ) = setindex! (A, sparse (x), I, findall (J))
2640
- setindex! (A:: SparseMatrixCSC , x:: Matrix , I:: AbstractVector{Bool} , J:: Integer ) = setindex! (A, sparse (x), findall (I), J)
2641
- setindex! (A:: SparseMatrixCSC , x:: Matrix , I:: AbstractVector{Bool} , J:: AbstractVector{Bool} ) = setindex! (A, sparse (x), findall (I), findall (J))
2642
- setindex! (A:: SparseMatrixCSC , x:: Matrix , I:: AbstractVector{<:Integer} , J:: AbstractVector{Bool} ) = setindex! (A, sparse (x), I, findall (J))
2643
- setindex! (A:: SparseMatrixCSC , x:: Matrix , I:: AbstractVector{Bool} , J:: AbstractVector{<:Integer} ) = setindex! (A, sparse (x), findall (I),J)
2644
-
2645
- setindex! (A:: Matrix , x:: SparseMatrixCSC , I:: Integer , J:: AbstractVector{Bool} ) = setindex! (A, Array (x), I, findall (J))
2646
- setindex! (A:: Matrix , x:: SparseMatrixCSC , I:: AbstractVector{Bool} , J:: Integer ) = setindex! (A, Array (x), findall (I), J)
2647
- setindex! (A:: Matrix , x:: SparseMatrixCSC , I:: AbstractVector{Bool} , J:: AbstractVector{Bool} ) = setindex! (A, Array (x), findall (I), findall (J))
2648
- setindex! (A:: Matrix , x:: SparseMatrixCSC , I:: AbstractVector{<:Integer} , J:: AbstractVector{Bool} ) = setindex! (A, Array (x), I, findall (J))
2649
- setindex! (A:: Matrix , x:: SparseMatrixCSC , I:: AbstractVector{Bool} , J:: AbstractVector{<:Integer} ) = setindex! (A, Array (x), findall (I), J)
2650
-
2651
- setindex! (A:: SparseMatrixCSC , x, I:: AbstractVector{Bool} ) = throw (BoundsError ())
2652
2500
function setindex! (A:: SparseMatrixCSC , x, I:: AbstractMatrix{Bool} )
2653
2501
checkbounds (A, I)
2654
2502
n = sum (I)
@@ -2782,7 +2630,7 @@ function setindex!(A::SparseMatrixCSC, x, I::AbstractVector{<:Real})
2782
2630
2783
2631
# copy from last position till current column
2784
2632
if (nadd > 0 )
2785
- colptrB[(lastcol+ 1 ): col] = colptrA[(lastcol+ 1 ): col] .+ nadd
2633
+ colptrB[(lastcol+ 1 ): col] . = colptrA[(lastcol+ 1 ): col] .+ nadd
2786
2634
copylen = r1 - aidx
2787
2635
if copylen > 0
2788
2636
copyto! (rowvalB, bidx, rowvalA, aidx, copylen)
@@ -2857,6 +2705,167 @@ function setindex!(A::SparseMatrixCSC, x, I::AbstractVector{<:Real})
2857
2705
A
2858
2706
end
2859
2707
2708
+ # Multi-value indexed assignment A[...] .= B gets represented as `broadcast!(identity, view(A, ...), B)`
2709
+ const _Idx = Union{Integer,AbstractVector{<: Integer }}
2710
+ const CSCAssignmentView{I<: Union{Tuple{_Idx},Tuple{_Idx,_Idx}} } = SubArray{<: Any ,<: Any ,<: SparseMatrixCSC ,I,false }
2711
+ _getij (S:: CSCAssignmentView{<:Tuple{AbstractVector,AbstractVector}} ) = S. indices
2712
+ _getij (S:: CSCAssignmentView{<:Tuple{Integer,Integer}} ) = (S. indices[1 ]: S. indices[1 ], S. indices[2 ]: S. indices[2 ])
2713
+ _getij (S:: CSCAssignmentView{<:Tuple{Integer,AbstractVector}} ) = (S. indices[1 ]: S. indices[1 ], S. indices[2 ])
2714
+ _getij (S:: CSCAssignmentView{<:Tuple{AbstractVector,Integer}} ) = (S. indices[1 ], S. indices[2 ]: S. indices[2 ])
2715
+ function _getij (S:: CSCAssignmentView{<:Tuple{Integer}} )
2716
+ v = CartesianIndices (S. parent)[S. indices[1 ]]
2717
+ return (v. I[1 ]: v. I[1 ], v. I[2 ]: v. I[2 ])
2718
+ end
2719
+ function _getij (S:: CSCAssignmentView {<: Tuple{AbstractArray{CartesianIndex{2}}} })
2720
+ V = reinterpret (Int, S. indices[1 ])
2721
+ return @views (V[1 : 2 : end ], V[2 : 2 : end ])
2722
+ end
2723
+ function _getij (S:: CSCAssignmentView{<:Tuple{AbstractArray}} )
2724
+ V = reinterpret (Int, CartesianIndices (S. parent)[S. indices[1 ]])
2725
+ return @views (V[1 : 2 : end ], V[2 : 2 : end ])
2726
+ end
2727
+
2728
+ function broadcast! (:: typeof (identity), V:: CSCAssignmentView , B:: SparseMatrixCSC )
2729
+ A = V. parent
2730
+ I, J = _getij (V)
2731
+ return multivaluesetindex! (A, B, I, J)
2732
+ end
2733
+ # Historically, we've only supported specialized methods based upon the value for Matrix
2734
+ # and Vector by converting them to SparseMatrixCSCs of the correct shape. This could be
2735
+ # extended to any AbstractArray in the future.
2736
+ broadcast! (:: typeof (identity), V:: CSCAssignmentView , B:: Matrix ) = broadcast! (identity, V, convert (SparseMatrixCSC, B))
2737
+ function broadcast! (:: typeof (identity), V:: CSCAssignmentView , x:: Vector )
2738
+ A = V. parent
2739
+ I, J, = _getij (V)
2740
+ return multivaluesetindex! (A, convert (SparseMatrixCSC, reshape (x, length (I), length (J))), I, J)
2741
+ end
2742
+
2743
+ # A[I,J] .= B
2744
+ function multivaluesetindex! (A:: SparseMatrixCSC{Tv} , B:: SparseMatrixCSC , I:: AbstractVector{T} , J:: AbstractVector{T} ) where {Tv,T<: Integer }
2745
+ if size (B,1 ) != length (I) || size (B,2 ) != length (J)
2746
+ throw (DimensionMismatch (" " ))
2747
+ end
2748
+
2749
+ issortedI = issorted (I)
2750
+ issortedJ = issorted (J)
2751
+
2752
+ if ! issortedI && ! issortedJ
2753
+ pI = sortperm (I); @inbounds I = I[pI]
2754
+ pJ = sortperm (J); @inbounds J = J[pJ]
2755
+ B = B[pI, pJ]
2756
+ elseif ! issortedI
2757
+ pI = sortperm (I); @inbounds I = I[pI]
2758
+ B = B[pI,:]
2759
+ elseif ! issortedJ
2760
+ pJ = sortperm (J); @inbounds J = J[pJ]
2761
+ B = B[:, pJ]
2762
+ end
2763
+
2764
+ m, n = size (A)
2765
+ mB, nB = size (B)
2766
+
2767
+ if (! isempty (I) && (I[1 ] < 1 || I[end ] > m)) || (! isempty (J) && (J[1 ] < 1 || J[end ] > n))
2768
+ throw (BoundsError (A, (I, J)))
2769
+ end
2770
+
2771
+ if isempty (I) || isempty (J)
2772
+ return A
2773
+ end
2774
+
2775
+ nI = length (I)
2776
+ nJ = length (J)
2777
+
2778
+ colptrA = A. colptr; rowvalA = A. rowval; nzvalA = A. nzval
2779
+ colptrB = B. colptr; rowvalB = B. rowval; nzvalB = B. nzval
2780
+
2781
+ nnzS = nnz (A) + nnz (B)
2782
+
2783
+ colptrS = copy (A. colptr)
2784
+ rowvalS = copy (A. rowval)
2785
+ nzvalS = copy (A. nzval)
2786
+
2787
+ resize! (rowvalA, nnzS)
2788
+ resize! (nzvalA, nnzS)
2789
+
2790
+ colB = 1
2791
+ asgn_col = J[colB]
2792
+
2793
+ I_asgn = falses (m)
2794
+ I_asgn[I] = true
2795
+
2796
+ ptrS = 1
2797
+
2798
+ @inbounds for col = 1 : n
2799
+
2800
+ # Copy column of A if it is not being assigned into
2801
+ if colB > nJ || col != J[colB]
2802
+ colptrA[col+ 1 ] = colptrA[col] + (colptrS[col+ 1 ]- colptrS[col])
2803
+
2804
+ for k = colptrS[col]: colptrS[col+ 1 ]- 1
2805
+ rowvalA[ptrS] = rowvalS[k]
2806
+ nzvalA[ptrS] = nzvalS[k]
2807
+ ptrS += 1
2808
+ end
2809
+ continue
2810
+ end
2811
+
2812
+ ptrA:: Int = colptrS[col]
2813
+ stopA:: Int = colptrS[col+ 1 ]
2814
+ ptrB:: Int = colptrB[colB]
2815
+ stopB:: Int = colptrB[colB+ 1 ]
2816
+
2817
+ while ptrA < stopA && ptrB < stopB
2818
+ rowA = rowvalS[ptrA]
2819
+ rowB = I[rowvalB[ptrB]]
2820
+ if rowA < rowB
2821
+ rowvalA[ptrS] = rowA
2822
+ nzvalA[ptrS] = I_asgn[rowA] ? zero (Tv) : nzvalS[ptrA]
2823
+ ptrS += 1
2824
+ ptrA += 1
2825
+ elseif rowB < rowA
2826
+ if nzvalB[ptrB] != zero (Tv)
2827
+ rowvalA[ptrS] = rowB
2828
+ nzvalA[ptrS] = nzvalB[ptrB]
2829
+ ptrS += 1
2830
+ end
2831
+ ptrB += 1
2832
+ else
2833
+ rowvalA[ptrS] = rowB
2834
+ nzvalA[ptrS] = nzvalB[ptrB]
2835
+ ptrS += 1
2836
+ ptrB += 1
2837
+ ptrA += 1
2838
+ end
2839
+ end
2840
+
2841
+ while ptrA < stopA
2842
+ rowA = rowvalS[ptrA]
2843
+ rowvalA[ptrS] = rowA
2844
+ nzvalA[ptrS] = I_asgn[rowA] ? zero (Tv) : nzvalS[ptrA]
2845
+ ptrS += 1
2846
+ ptrA += 1
2847
+ end
2848
+
2849
+ while ptrB < stopB
2850
+ rowB = I[rowvalB[ptrB]]
2851
+ if nzvalB[ptrB] != zero (Tv)
2852
+ rowvalA[ptrS] = rowB
2853
+ nzvalA[ptrS] = nzvalB[ptrB]
2854
+ ptrS += 1
2855
+ end
2856
+ ptrB += 1
2857
+ end
2858
+
2859
+ colptrA[col+ 1 ] = ptrS
2860
+ colB += 1
2861
+ end
2862
+
2863
+ deleteat! (rowvalA, colptrA[end ]: length (rowvalA))
2864
+ deleteat! (nzvalA, colptrA[end ]: length (nzvalA))
2865
+
2866
+ return A
2867
+ end
2868
+
2860
2869
# # dropstored! methods
2861
2870
"""
2862
2871
dropstored!(A::SparseMatrixCSC, i::Integer, j::Integer)
0 commit comments