1use crate::coo_array::CooArray;
8use crate::csr_array::CsrArray;
9use crate::error::{SparseError, SparseResult};
10use crate::sparray::{SparseArray, SparseSum};
11use crate::sym_coo::SymCooArray;
12use crate::sym_csr::SymCsrArray;
13use scirs2_core::numeric::{Float, SparseElement};
14use std::fmt::Debug;
15use std::ops::{Add, Div, Mul, Sub};
16
17pub trait SymSparseArray<T>: SparseArray<T>
23where
24 T: SparseElement + Div<Output = T> + Float + PartialOrd + 'static,
25{
26 fn nnz_stored(&self) -> usize;
35
36 fn is_symmetric(&self) -> bool {
45 true
46 }
47
48 fn to_csr(&self) -> SparseResult<CsrArray<T>>;
54
55 fn to_coo(&self) -> SparseResult<CooArray<T>>;
61
62 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>>;
68
69 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>>;
75}
76
77impl<T> SymSparseArray<T> for SymCsrArray<T>
79where
80 T: Float
81 + SparseElement
82 + Debug
83 + Copy
84 + 'static
85 + Add<Output = T>
86 + Sub<Output = T>
87 + Mul<Output = T>
88 + Div<Output = T>
89 + scirs2_core::simd_ops::SimdUnifiedOps
90 + SparseElement
91 + Send
92 + Sync,
93{
94 fn nnz_stored(&self) -> usize {
95 self.inner().nnz_stored()
96 }
97
98 fn to_csr(&self) -> SparseResult<CsrArray<T>> {
99 self.to_csr_array()
100 }
101
102 fn to_coo(&self) -> SparseResult<CooArray<T>> {
103 let csr_inner = self.inner();
105 let shape = csr_inner.shape;
106
107 let mut rows = Vec::new();
109 let mut cols = Vec::new();
110 let mut data = Vec::new();
111
112 for i in 0..shape.0 {
113 for j_ptr in csr_inner.indptr[i]..csr_inner.indptr[i + 1] {
114 let j = csr_inner.indices[j_ptr];
115 let val = csr_inner.data[j_ptr];
116
117 rows.push(i);
119 cols.push(j);
120 data.push(val);
121
122 if i != j {
124 rows.push(j);
125 cols.push(i);
126 data.push(val);
127 }
128 }
129 }
130
131 CooArray::from_triplets(&rows, &cols, &data, shape, false)
133 }
134
135 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>> {
136 Ok(Clone::clone(self))
138 }
139
140 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>> {
141 let csr_inner = self.inner();
143
144 let mut data = Vec::new();
146 let mut rows = Vec::new();
147 let mut cols = Vec::new();
148
149 for i in 0..csr_inner.shape.0 {
150 for j in csr_inner.indptr[i]..csr_inner.indptr[i + 1] {
151 let col = csr_inner.indices[j];
152 let val = csr_inner.data[j];
153
154 data.push(val);
155 rows.push(i);
156 cols.push(col);
157 }
158 }
159
160 use crate::sym_coo::SymCooMatrix;
161 let sym_coo = SymCooMatrix::new(data, rows, cols, csr_inner.shape)?;
162
163 Ok(SymCooArray::new(sym_coo))
164 }
165}
166
167impl<T> SymSparseArray<T> for SymCooArray<T>
169where
170 T: Float
171 + SparseElement
172 + Debug
173 + Copy
174 + 'static
175 + Add<Output = T>
176 + Sub<Output = T>
177 + Mul<Output = T>
178 + Div<Output = T>
179 + scirs2_core::simd_ops::SimdUnifiedOps
180 + SparseElement
181 + Send
182 + Sync,
183{
184 fn nnz_stored(&self) -> usize {
185 self.inner().nnz_stored()
186 }
187
188 fn to_csr(&self) -> SparseResult<CsrArray<T>> {
189 let coo = self.to_coo_array()?;
191 match coo.to_csr() {
192 Ok(boxed_csr) => {
193 match boxed_csr.as_any().downcast_ref::<CsrArray<T>>() {
195 Some(csr_array) => Ok(csr_array.clone()),
196 None => Err(SparseError::ConversionError(
197 "Failed to downcast to CsrArray".to_string(),
198 )),
199 }
200 }
201 Err(e) => Err(e),
202 }
203 }
204
205 fn to_coo(&self) -> SparseResult<CooArray<T>> {
206 self.to_coo_array()
207 }
208
209 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>> {
210 let coo_inner = self.inner();
213
214 let data = coo_inner.data.clone();
216 let rows = coo_inner.rows.clone();
217 let cols = coo_inner.cols.clone();
218 let shape = coo_inner.shape;
219
220 let csr = crate::csr::CsrMatrix::new(data, rows, cols, shape)?;
222
223 use crate::sym_csr::SymCsrMatrix;
225
226 let mut sym_data = Vec::new();
228 let mut sym_indices = Vec::new();
229 let mut sym_indptr = vec![0];
230 let n = shape.0;
231
232 for i in 0..n {
233 for j_ptr in csr.indptr[i]..csr.indptr[i + 1] {
234 let j = csr.indices[j_ptr];
235 let val = csr.data[j_ptr];
236
237 if j <= i {
239 sym_data.push(val);
240 sym_indices.push(j);
241 }
242 }
243
244 sym_indptr.push(sym_data.len());
245 }
246
247 let sym_csr = SymCsrMatrix::new(sym_data, sym_indptr, sym_indices, shape)?;
248
249 Ok(SymCsrArray::new(sym_csr))
250 }
251
252 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>> {
253 Ok(Clone::clone(self))
255 }
256}
257
258impl<T> SparseArray<T> for SymCsrArray<T>
260where
261 T: Float
262 + SparseElement
263 + Debug
264 + Copy
265 + 'static
266 + Add<Output = T>
267 + Sub<Output = T>
268 + Mul<Output = T>
269 + Div<Output = T>
270 + scirs2_core::simd_ops::SimdUnifiedOps
271 + SparseElement
272 + Send
273 + Sync,
274{
275 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
276 let coo_array = <Self as SymSparseArray<T>>::to_coo(self)?;
277 Ok(Box::new(coo_array))
278 }
279
280 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
281 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
283 Ok(Box::new(csr))
284 }
285 fn shape(&self) -> (usize, usize) {
286 self.inner().shape()
287 }
288
289 fn nnz(&self) -> usize {
290 self.inner().nnz()
291 }
292
293 fn dtype(&self) -> &str {
294 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
295 "f32"
296 } else {
297 "f64"
298 }
299 }
300
301 fn get(&self, row: usize, col: usize) -> T {
302 self.inner().get(row, col)
303 }
304
305 fn to_array(&self) -> scirs2_core::ndarray::Array2<T> {
306 let dense = self.inner().to_dense();
308 let mut array = scirs2_core::ndarray::Array2::zeros(self.shape());
309
310 for i in 0..dense.len() {
311 for j in 0..dense[i].len() {
312 array[[i, j]] = dense[i][j];
313 }
314 }
315
316 array
317 }
318
319 fn toarray(&self) -> scirs2_core::ndarray::Array2<T> {
320 self.to_array()
321 }
322
323 fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()> {
324 Err(SparseError::NotImplemented(
325 "Setting individual elements in SymCsrArray is not supported. Convert to another format first.".to_string()
326 ))
327 }
328
329 fn dot_vector(
330 &self,
331 other: &scirs2_core::ndarray::ArrayView1<T>,
332 ) -> SparseResult<scirs2_core::ndarray::Array1<T>> {
333 crate::sym_ops::sym_csr_matvec(self.inner(), other)
335 }
336
337 fn copy(&self) -> Box<dyn SparseArray<T>> {
338 Box::new(Clone::clone(self))
339 }
340
341 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
342 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
345 let result = self_csr.sub(other)?;
346
347 Ok(result)
349 }
350
351 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
352 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
354 self_csr.div(other)
355 }
356
357 fn eliminate_zeros(&mut self) {
358 }
360
361 fn sort_indices(&mut self) {
362 }
364
365 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
366 Box::new(Clone::clone(self))
368 }
369
370 fn has_sorted_indices(&self) -> bool {
371 true
372 }
373
374 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
375 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
377 SparseArray::<T>::sum(&csr, axis)
378 }
379
380 fn max(&self) -> T {
381 match <Self as SymSparseArray<T>>::to_csr(self) {
383 Ok(csr) => SparseArray::<T>::max(&csr),
384 Err(_) => T::nan(), }
386 }
387
388 fn min(&self) -> T {
389 match <Self as SymSparseArray<T>>::to_csr(self) {
391 Ok(csr) => SparseArray::<T>::min(&csr),
392 Err(_) => T::nan(), }
394 }
395
396 fn slice(
397 &self,
398 rows: (usize, usize),
399 cols: (usize, usize),
400 ) -> SparseResult<Box<dyn SparseArray<T>>> {
401 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
404 csr.slice(rows, cols)
405 }
406
407 fn as_any(&self) -> &dyn std::any::Any {
408 self
409 }
410
411 fn find(
412 &self,
413 ) -> (
414 scirs2_core::ndarray::Array1<usize>,
415 scirs2_core::ndarray::Array1<usize>,
416 scirs2_core::ndarray::Array1<T>,
417 ) {
418 match <Self as SymSparseArray<T>>::to_csr(self) {
420 Ok(csr) => csr.find(),
421 Err(_) => (
422 scirs2_core::ndarray::Array1::from_vec(Vec::new()),
423 scirs2_core::ndarray::Array1::from_vec(Vec::new()),
424 scirs2_core::ndarray::Array1::from_vec(Vec::new()),
425 ),
426 }
427 }
428
429 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
430 let selfshape = self.shape();
432 let othershape = other.shape();
433
434 if selfshape != othershape {
435 return Err(crate::error::SparseError::DimensionMismatch {
436 expected: selfshape.0,
437 found: othershape.0,
438 });
439 }
440
441 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
443 let other_csr_box = other.to_csr()?;
444
445 match other_csr_box.as_any().downcast_ref::<CsrArray<T>>() {
447 Some(other_csr) => {
448 let result = self_csr.add(other_csr)?;
450
451 use crate::csr::CsrMatrix;
456
457 let (rows, cols, data) = result.find();
459 let csr_matrix =
460 CsrMatrix::new(data.to_vec(), rows.to_vec(), cols.to_vec(), result.shape())?;
461
462 use crate::sym_csr::SymCsrMatrix;
464 let sym_csr = SymCsrMatrix::from_csr(&csr_matrix)?;
465
466 let sym_csr_array = SymCsrArray::new(sym_csr);
468 Ok(Box::new(sym_csr_array) as Box<dyn SparseArray<T>>)
469 }
470 None => {
471 let self_dense = self.to_array();
473 let other_dense = other.to_array();
474
475 let mut result_dense = scirs2_core::ndarray::Array2::zeros(selfshape);
477 for i in 0..selfshape.0 {
478 for j in 0..selfshape.1 {
479 result_dense[[i, j]] = self_dense[[i, j]] + other_dense[[i, j]];
480 }
481 }
482
483 let mut rows = Vec::new();
486 let mut cols = Vec::new();
487 let mut values = Vec::new();
488
489 for i in 0..selfshape.0 {
490 for j in 0..selfshape.1 {
491 let val = result_dense[[i, j]];
492 if val != T::sparse_zero() {
493 rows.push(i);
494 cols.push(j);
495 values.push(val);
496 }
497 }
498 }
499
500 let csr = CsrArray::from_triplets(&rows, &cols, &values, selfshape, false)?;
501 Ok(Box::new(csr) as Box<dyn SparseArray<T>>)
502 }
503 }
504 }
505
506 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
507 let selfshape = self.shape();
509 let othershape = other.shape();
510
511 if selfshape != othershape {
512 return Err(crate::error::SparseError::DimensionMismatch {
513 expected: selfshape.0,
514 found: othershape.0,
515 });
516 }
517
518 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
520 let other_csr_box = other.to_csr()?;
521
522 match other_csr_box.as_any().downcast_ref::<CsrArray<T>>() {
524 Some(other_csr) => {
525 let result = self_csr.mul(other_csr)?;
527
528 let (rows, cols, data) = result.find();
533
534 use crate::csr::CsrMatrix;
536 let csr_matrix =
537 CsrMatrix::new(data.to_vec(), rows.to_vec(), cols.to_vec(), result.shape())?;
538
539 use crate::sym_csr::SymCsrMatrix;
541 let sym_csr = SymCsrMatrix::from_csr(&csr_matrix)?;
542
543 let sym_csr_array = SymCsrArray::new(sym_csr);
545 Ok(Box::new(sym_csr_array) as Box<dyn SparseArray<T>>)
546 }
547 None => {
548 let self_dense = self.to_array();
550 let other_dense = other.to_array();
551
552 let mut result_dense = scirs2_core::ndarray::Array2::zeros(selfshape);
554 for i in 0..selfshape.0 {
555 for j in 0..selfshape.1 {
556 result_dense[[i, j]] = self_dense[[i, j]] * other_dense[[i, j]];
557 }
558 }
559
560 let mut rows = Vec::new();
563 let mut cols = Vec::new();
564 let mut values = Vec::new();
565
566 for i in 0..selfshape.0 {
567 for j in 0..selfshape.1 {
568 let val = result_dense[[i, j]];
569 if val != T::sparse_zero() {
570 rows.push(i);
571 cols.push(j);
572 values.push(val);
573 }
574 }
575 }
576
577 let csr = CsrArray::from_triplets(&rows, &cols, &values, selfshape, false)?;
578 Ok(Box::new(csr) as Box<dyn SparseArray<T>>)
579 }
580 }
581 }
582
583 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
584 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
588 let result = self_csr.dot(other)?;
589
590 Ok(result)
594 }
595
596 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
597 Ok(Box::new(Clone::clone(self)))
599 }
600
601 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
602 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
604 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
605 csr_box.to_csc()
606 }
607
608 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
609 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
611 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
612 csr_box.to_dia()
613 }
614
615 fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
616 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
618 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
619 csr_box.to_dok()
620 }
621
622 fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
623 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
625 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
626 csr_box.to_lil()
627 }
628
629 fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
630 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
632 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
633 csr_box.to_bsr()
634 }
635}
636
637impl<T> SparseArray<T> for SymCooArray<T>
639where
640 T: Float
641 + SparseElement
642 + Debug
643 + Copy
644 + 'static
645 + Add<Output = T>
646 + Sub<Output = T>
647 + Mul<Output = T>
648 + Div<Output = T>
649 + scirs2_core::simd_ops::SimdUnifiedOps
650 + SparseElement
651 + Send
652 + Sync,
653{
654 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
655 let coo_array = <Self as SymSparseArray<T>>::to_coo(self)?;
656 Ok(Box::new(coo_array))
657 }
658
659 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
660 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
662 Ok(Box::new(csr))
663 }
664 fn shape(&self) -> (usize, usize) {
665 self.inner().shape()
666 }
667
668 fn nnz(&self) -> usize {
669 self.inner().nnz()
670 }
671
672 fn dtype(&self) -> &str {
673 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
674 "f32"
675 } else {
676 "f64"
677 }
678 }
679
680 fn get(&self, row: usize, col: usize) -> T {
681 self.inner().get(row, col)
682 }
683
684 fn to_array(&self) -> scirs2_core::ndarray::Array2<T> {
685 let dense = self.inner().to_dense();
687 let mut array = scirs2_core::ndarray::Array2::zeros(self.shape());
688
689 for i in 0..dense.len() {
690 for j in 0..dense[i].len() {
691 array[[i, j]] = dense[i][j];
692 }
693 }
694
695 array
696 }
697
698 fn toarray(&self) -> scirs2_core::ndarray::Array2<T> {
699 self.to_array()
700 }
701
702 fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()> {
703 Err(SparseError::NotImplemented(
704 "Setting individual elements in SymCooArray is not supported. Convert to another format first.".to_string()
705 ))
706 }
707
708 fn dot_vector(
709 &self,
710 other: &scirs2_core::ndarray::ArrayView1<T>,
711 ) -> SparseResult<scirs2_core::ndarray::Array1<T>> {
712 crate::sym_ops::sym_coo_matvec(self.inner(), other)
714 }
715
716 fn copy(&self) -> Box<dyn SparseArray<T>> {
717 Box::new(Clone::clone(self))
718 }
719
720 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
721 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
723 self_csr.sub(other)
724 }
725
726 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
727 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
729 self_csr.div(other)
730 }
731
732 fn eliminate_zeros(&mut self) {
733 }
736
737 fn sort_indices(&mut self) {
738 }
741
742 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
743 match self.to_sym_csr() {
745 Ok(csr) => Box::new(csr),
746 Err(_) => Box::new(Clone::clone(self)), }
748 }
749
750 fn has_sorted_indices(&self) -> bool {
751 false
752 }
753
754 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
755 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
757 SparseArray::<T>::sum(&csr, axis)
758 }
759
760 fn max(&self) -> T {
761 match <Self as SymSparseArray<T>>::to_csr(self) {
763 Ok(csr) => SparseArray::<T>::max(&csr),
764 Err(_) => T::nan(), }
766 }
767
768 fn min(&self) -> T {
769 match <Self as SymSparseArray<T>>::to_csr(self) {
771 Ok(csr) => SparseArray::<T>::min(&csr),
772 Err(_) => T::nan(), }
774 }
775
776 fn slice(
777 &self,
778 rows: (usize, usize),
779 cols: (usize, usize),
780 ) -> SparseResult<Box<dyn SparseArray<T>>> {
781 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
783 csr.slice(rows, cols)
784 }
785
786 fn as_any(&self) -> &dyn std::any::Any {
787 self
788 }
789
790 fn find(
791 &self,
792 ) -> (
793 scirs2_core::ndarray::Array1<usize>,
794 scirs2_core::ndarray::Array1<usize>,
795 scirs2_core::ndarray::Array1<T>,
796 ) {
797 match <Self as SymSparseArray<T>>::to_coo(self) {
799 Ok(coo) => coo.find(),
800 Err(_) => (
801 scirs2_core::ndarray::Array1::from_vec(Vec::new()),
802 scirs2_core::ndarray::Array1::from_vec(Vec::new()),
803 scirs2_core::ndarray::Array1::from_vec(Vec::new()),
804 ),
805 }
806 }
807
808 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
809 self.to_sym_csr()?.add(other)
811 }
812
813 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
814 self.to_sym_csr()?.mul(other)
816 }
817
818 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
819 <Self as SymSparseArray<T>>::to_csr(self)?.dot(other)
821 }
822
823 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
824 Ok(Box::new(Clone::clone(self)))
826 }
827
828 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
829 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
831 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
832 csr_box.to_csc()
833 }
834
835 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
836 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
838 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
839 csr_box.to_dia()
840 }
841
842 fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
843 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
845 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
846 csr_box.to_dok()
847 }
848
849 fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
850 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
852 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
853 csr_box.to_lil()
854 }
855
856 fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
857 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
859 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
860 csr_box.to_bsr()
861 }
862}
863
864#[cfg(test)]
865mod tests {
866 use super::*;
867 use crate::sym_csr::{SymCsrArray, SymCsrMatrix};
868
869 fn create_test_sym_csr() -> SymCsrArray<f64> {
871 let data = vec![2.0, 1.0, 2.0, 3.0, 1.0];
882 let indices = vec![0, 0, 1, 1, 2];
883 let indptr = vec![0, 1, 3, 5];
884
885 let sym_matrix = SymCsrMatrix::new(data, indptr, indices, (3, 3)).unwrap();
886 SymCsrArray::new(sym_matrix)
887 }
888
889 #[test]
890 fn test_sym_sparse_array_trait() {
891 let sym_csr = create_test_sym_csr();
892
893 assert_eq!(sym_csr.shape(), (3, 3));
895 assert!(sym_csr.is_symmetric());
896
897 assert_eq!(sym_csr.get(0, 0), 2.0);
899 assert_eq!(sym_csr.get(0, 1), 1.0);
900 assert_eq!(sym_csr.get(1, 0), 1.0); assert_eq!(sym_csr.nnz_stored(), 5); assert_eq!(sym_csr.nnz(), 7); let sym_coo = sym_csr.to_sym_coo().unwrap();
908 assert_eq!(sym_coo.shape(), (3, 3));
909 assert!(sym_coo.is_symmetric());
910
911 let csr = SymSparseArray::<f64>::to_csr(&sym_csr).unwrap();
912 assert_eq!(csr.shape(), (3, 3));
913
914 let coo = SymSparseArray::<f64>::to_coo(&sym_csr).unwrap();
915 assert_eq!(coo.shape(), (3, 3));
916
917 let (rows, _cols, _data) = sym_csr.find();
919 assert!(rows.len() > sym_csr.nnz_stored()); }
921
922 #[test]
923 fn test_sym_sparse_array_operations() {
924 let sym_csr = create_test_sym_csr();
925
926 let sym_csr2 = create_test_sym_csr();
928
929 let sum = sym_csr.add(&sym_csr2).unwrap();
931 assert_eq!(sum.shape(), (3, 3));
932 assert_eq!(sum.get(0, 0), 4.0); assert_eq!(sum.get(0, 1), 2.0); assert_eq!(sum.get(1, 0), 2.0); let prod = sym_csr.mul(&sym_csr2).unwrap();
938 assert_eq!(prod.shape(), (3, 3));
939 assert_eq!(prod.get(0, 0), 4.0); assert_eq!(prod.get(0, 1), 1.0); assert_eq!(prod.get(1, 0), 1.0); let dot = sym_csr.dot(&sym_csr2).unwrap();
945 assert_eq!(dot.shape(), (3, 3));
946
947 let trans = sym_csr.transpose().unwrap();
949 assert_eq!(trans.shape(), sym_csr.shape());
950 assert_eq!(SparseArray::get(&*trans, 0, 1), sym_csr.get(0, 1));
951 assert_eq!(SparseArray::get(&*trans, 1, 0), sym_csr.get(1, 0));
952 }
953}