1+ """ 
2+     SparseArray{T, N} <: AbstractArray{T, N} 
3+ 
4+ A multidimensional sparse array that stores only non-zero elements efficiently. 
5+ 
6+ # Fields 
7+ 
8+   - `data::Dict{CartesianIndex{N}, T}`: Dictionary mapping indices to non-zero values 
9+   - `dims::NTuple{N, Int}`: Dimensions of the array 
10+   - `default_value::T`: Default value for unset indices (typically zero) 
11+ 
12+ # Examples 
13+ 
14+ ```julia 
15+ # Create a 3x3 sparse matrix 
16+ A = SparseArray{Float64, 2}((3, 3)) 
17+ A[1, 1] = 5.0 
18+ A[2, 3] = 3.0 
19+ 
20+ # Create from existing data 
21+ B = SparseArray([1 0 3; 0 0 0; 2 0 0]) 
22+ ``` 
23+ """ 
24+ struct  SparseArray{T, N} <:  AbstractArray{T, N} 
25+     data:: Dict{CartesianIndex{N}, T} 
26+     dims:: NTuple{N, Int} 
27+     default_value:: T 
28+ 
29+     function  SparseArray {T, N} (dims:: NTuple{N, Int} , default_value:: T  =  zero (T)) where  {T, N}
30+         return  new {T, N} (Dict {CartesianIndex{N}, T} (), dims, default_value)
31+     end 
32+ end 
33+ 
34+ #  Convenience constructors
35+ SparseArray {T} (dims:: NTuple{N, Int} , default_value:: T  =  zero (T)) where  {T, N} = 
36+     SparseArray {T, N} (dims, default_value)
37+ 
38+ SparseArray {T} (dims:: Vararg{Int, N} ) where  {T, N} = 
39+     SparseArray {T, N} (dims, zero (T))
40+ 
41+ #  Constructor from dense array
42+ function  SparseArray (A:: AbstractArray{T, N} ) where  {T, N}
43+     sparse_array =  SparseArray {T, N} (size (A))
44+     for  I in  CartesianIndices (A)
45+         val =  A[I]
46+         if  val !=  sparse_array. default_value
47+             sparse_array. data[I] =  val
48+         end 
49+     end 
50+     return  sparse_array
51+ end 
52+ 
53+ #  Required AbstractArray interface
54+ Base. size (A:: SparseArray ) =  A. dims
55+ Base. IndexStyle (:: Type{<:SparseArray} ) =  IndexCartesian ()
56+ 
57+ #  Indexing
58+ @inline  function  Base. getindex (A:: SparseArray{T, N} , I:: Vararg{Int, N} ) where  {T, N}
59+     @boundscheck  checkbounds (A, I... )
60+     idx =  CartesianIndex (I)
61+     return  get (A. data, idx, A. default_value)
62+ end 
63+ 
64+ @inline  function  Base. getindex (A:: SparseArray , I:: CartesianIndex )
65+     @boundscheck  checkbounds (A, I)
66+     return  get (A. data, I, A. default_value)
67+ end 
68+ 
69+ @inline  function  Base. setindex! (A:: SparseArray{T, N} , val, I:: Vararg{Int, N} ) where  {T, N}
70+     @boundscheck  checkbounds (A, I... )
71+     idx =  CartesianIndex (I)
72+     if  val ==  A. default_value
73+         delete! (A. data, idx)
74+     else 
75+         A. data[idx] =  val
76+     end 
77+     return  val
78+ end 
79+ 
80+ @inline  function  Base. setindex! (A:: SparseArray , val, I:: CartesianIndex )
81+     @boundscheck  checkbounds (A, I)
82+     if  val ==  A. default_value
83+         delete! (A. data, I)
84+     else 
85+         A. data[I] =  val
86+     end 
87+     return  val
88+ end 
89+ 
90+ #  Iteration
91+ function  Base. iterate (A:: SparseArray )
92+     iter_state =  iterate (CartesianIndices (A))
93+     isnothing (iter_state) &&  return  nothing 
94+     idx, state =  iter_state
95+     return  (A[idx], state)
96+ end 
97+ 
98+ function  Base. iterate (A:: SparseArray , state)
99+     iter_state =  iterate (CartesianIndices (A), state)
100+     isnothing (iter_state) &&  return  nothing 
101+     idx, new_state =  iter_state
102+     return  (A[idx], new_state)
103+ end 
104+ 
105+ #  Additional useful methods
106+ """ 
107+     nnz(A::SparseArray) 
108+ 
109+ Return the number of stored (non-zero) elements in the sparse array. 
110+ """ 
111+ nnz (A:: SparseArray ) =  length (A. data)
112+ 
113+ """ 
114+     sparsity(A::SparseArray) 
115+ 
116+ Return the sparsity ratio (fraction of zero elements) of the array. 
117+ """ 
118+ sparsity (A:: SparseArray ) =  1.0  -  nnz (A) /  length (A)
119+ 
120+ """ 
121+     stored_indices(A::SparseArray) 
122+ 
123+ Return an iterator over the indices that have stored values. 
124+ """ 
125+ stored_indices (A:: SparseArray ) =  keys (A. data)
126+ 
127+ """ 
128+     stored_values(A::SparseArray) 
129+ 
130+ Return an iterator over the stored non-zero values. 
131+ """ 
132+ stored_values (A:: SparseArray ) =  values (A. data)
133+ 
134+ """ 
135+     stored_pairs(A::SparseArray) 
136+ 
137+ Return an iterator over (index, value) pairs for stored elements. 
138+ """ 
139+ stored_pairs (A:: SparseArray ) =  pairs (A. data)
140+ 
141+ #  Display
142+ function  Base. show (io:: IO , :: MIME"text/plain" , A:: SparseArray{T, N} ) where  {T, N}
143+     println (io, " $(size (A))  SparseArray{$T , $N } with $(nnz (A))  stored entries:"  )
144+     if  nnz (A) >  0 
145+         for  (idx, val) in  stored_pairs (A)
146+             println (io, "   $idx   =>  $val "  )
147+         end 
148+     end 
149+ end 
150+ 
151+ #  Basic arithmetic operations
152+ Base.:(== )(A:: SparseArray , B:: SparseArray ) = 
153+     size (A) ==  size (B) &&  A. default_value ==  B. default_value &&  A. data ==  B. data
154+ 
155+ #  Copy
156+ function  Base. copy (A:: SparseArray{T, N} ) where  {T, N}
157+     B =  SparseArray {T, N} (A. dims, A. default_value)
158+     for  (k, v) in  A. data
159+         B. data[k] =  v
160+     end 
161+     return  B
162+ end 
163+ 
164+ Base. similar (A:: SparseArray{T, N} ) where  {T, N} = 
165+     SparseArray {T, N} (A. dims, A. default_value)
166+ 
167+ Base. similar (A:: SparseArray{T, N} , :: Type{S} ) where  {T, S, N} = 
168+     SparseArray {S, N} (A. dims, zero (S))
0 commit comments