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 num_traits::Float;
14use std::fmt::Debug;
15use std::ops::{Add, Div, Mul, Sub};
16
17pub trait SymSparseArray<T>: SparseArray<T>
23where
24 T: Float + Debug + Copy + '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 + Debug
82 + Copy
83 + 'static
84 + Add<Output = T>
85 + Sub<Output = T>
86 + Mul<Output = T>
87 + Div<Output = T>
88 + scirs2_core::simd_ops::SimdUnifiedOps
89 + Send
90 + Sync,
91{
92 fn nnz_stored(&self) -> usize {
93 self.inner().nnz_stored()
94 }
95
96 fn to_csr(&self) -> SparseResult<CsrArray<T>> {
97 self.to_csr_array()
98 }
99
100 fn to_coo(&self) -> SparseResult<CooArray<T>> {
101 let csr_inner = self.inner();
103 let shape = csr_inner.shape;
104
105 let mut rows = Vec::new();
107 let mut cols = Vec::new();
108 let mut data = Vec::new();
109
110 for i in 0..shape.0 {
111 for j_ptr in csr_inner.indptr[i]..csr_inner.indptr[i + 1] {
112 let j = csr_inner.indices[j_ptr];
113 let val = csr_inner.data[j_ptr];
114
115 rows.push(i);
117 cols.push(j);
118 data.push(val);
119
120 if i != j {
122 rows.push(j);
123 cols.push(i);
124 data.push(val);
125 }
126 }
127 }
128
129 CooArray::from_triplets(&rows, &cols, &data, shape, false)
131 }
132
133 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>> {
134 Ok(self.clone())
136 }
137
138 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>> {
139 let csr_inner = self.inner();
141
142 let mut data = Vec::new();
144 let mut rows = Vec::new();
145 let mut cols = Vec::new();
146
147 for i in 0..csr_inner.shape.0 {
148 for j in csr_inner.indptr[i]..csr_inner.indptr[i + 1] {
149 let col = csr_inner.indices[j];
150 let val = csr_inner.data[j];
151
152 data.push(val);
153 rows.push(i);
154 cols.push(col);
155 }
156 }
157
158 use crate::sym_coo::SymCooMatrix;
159 let sym_coo = SymCooMatrix::new(data, rows, cols, csr_inner.shape)?;
160
161 Ok(SymCooArray::new(sym_coo))
162 }
163}
164
165impl<T> SymSparseArray<T> for SymCooArray<T>
167where
168 T: Float
169 + Debug
170 + Copy
171 + 'static
172 + Add<Output = T>
173 + Sub<Output = T>
174 + Mul<Output = T>
175 + Div<Output = T>
176 + scirs2_core::simd_ops::SimdUnifiedOps
177 + Send
178 + Sync,
179{
180 fn nnz_stored(&self) -> usize {
181 self.inner().nnz_stored()
182 }
183
184 fn to_csr(&self) -> SparseResult<CsrArray<T>> {
185 let coo = self.to_coo_array()?;
187 match coo.to_csr() {
188 Ok(boxed_csr) => {
189 match boxed_csr.as_any().downcast_ref::<CsrArray<T>>() {
191 Some(csr_array) => Ok(csr_array.clone()),
192 None => Err(SparseError::ConversionError(
193 "Failed to downcast to CsrArray".to_string(),
194 )),
195 }
196 }
197 Err(e) => Err(e),
198 }
199 }
200
201 fn to_coo(&self) -> SparseResult<CooArray<T>> {
202 self.to_coo_array()
203 }
204
205 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>> {
206 let coo_inner = self.inner();
209
210 let data = coo_inner.data.clone();
212 let rows = coo_inner.rows.clone();
213 let cols = coo_inner.cols.clone();
214 let shape = coo_inner.shape;
215
216 let csr = crate::csr::CsrMatrix::new(data, rows, cols, shape)?;
218
219 use crate::sym_csr::SymCsrMatrix;
221
222 let mut sym_data = Vec::new();
224 let mut sym_indices = Vec::new();
225 let mut sym_indptr = vec![0];
226 let n = shape.0;
227
228 for i in 0..n {
229 for j_ptr in csr.indptr[i]..csr.indptr[i + 1] {
230 let j = csr.indices[j_ptr];
231 let val = csr.data[j_ptr];
232
233 if j <= i {
235 sym_data.push(val);
236 sym_indices.push(j);
237 }
238 }
239
240 sym_indptr.push(sym_data.len());
241 }
242
243 let sym_csr = SymCsrMatrix::new(sym_data, sym_indptr, sym_indices, shape)?;
244
245 Ok(SymCsrArray::new(sym_csr))
246 }
247
248 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>> {
249 Ok(self.clone())
251 }
252}
253
254impl<T> SparseArray<T> for SymCsrArray<T>
256where
257 T: Float
258 + Debug
259 + Copy
260 + 'static
261 + Add<Output = T>
262 + Sub<Output = T>
263 + Mul<Output = T>
264 + Div<Output = T>
265 + scirs2_core::simd_ops::SimdUnifiedOps
266 + Send
267 + Sync,
268{
269 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
270 let coo_array = <Self as SymSparseArray<T>>::to_coo(self)?;
271 Ok(Box::new(coo_array))
272 }
273
274 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
275 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
277 Ok(Box::new(csr))
278 }
279 fn shape(&self) -> (usize, usize) {
280 self.inner().shape()
281 }
282
283 fn nnz(&self) -> usize {
284 self.inner().nnz()
285 }
286
287 fn dtype(&self) -> &str {
288 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
289 "f32"
290 } else {
291 "f64"
292 }
293 }
294
295 fn get(&self, row: usize, col: usize) -> T {
296 self.inner().get(row, col)
297 }
298
299 fn to_array(&self) -> ndarray::Array2<T> {
300 let dense = self.inner().to_dense();
302 let mut array = ndarray::Array2::zeros(self.shape());
303
304 for i in 0..dense.len() {
305 for j in 0..dense[i].len() {
306 array[[i, j]] = dense[i][j];
307 }
308 }
309
310 array
311 }
312
313 fn toarray(&self) -> ndarray::Array2<T> {
314 self.to_array()
315 }
316
317 fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()> {
318 Err(SparseError::NotImplemented(
319 "Setting individual elements in SymCsrArray is not supported. Convert to another format first.".to_string()
320 ))
321 }
322
323 fn dot_vector(&self, other: &ndarray::ArrayView1<T>) -> SparseResult<ndarray::Array1<T>> {
324 crate::sym_ops::sym_csr_matvec(self.inner(), other)
326 }
327
328 fn copy(&self) -> Box<dyn SparseArray<T>> {
329 Box::new(self.clone())
330 }
331
332 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
333 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
336 let result = self_csr.sub(other)?;
337
338 Ok(result)
340 }
341
342 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
343 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
345 self_csr.div(other)
346 }
347
348 fn eliminate_zeros(&mut self) {
349 }
351
352 fn sort_indices(&mut self) {
353 }
355
356 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
357 Box::new(self.clone())
359 }
360
361 fn has_sorted_indices(&self) -> bool {
362 true
363 }
364
365 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
366 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
368 SparseArray::<T>::sum(&csr, axis)
369 }
370
371 fn max(&self) -> T {
372 match <Self as SymSparseArray<T>>::to_csr(self) {
374 Ok(csr) => SparseArray::<T>::max(&csr),
375 Err(_) => T::nan(), }
377 }
378
379 fn min(&self) -> T {
380 match <Self as SymSparseArray<T>>::to_csr(self) {
382 Ok(csr) => SparseArray::<T>::min(&csr),
383 Err(_) => T::nan(), }
385 }
386
387 fn slice(
388 &self,
389 rows: (usize, usize),
390 cols: (usize, usize),
391 ) -> SparseResult<Box<dyn SparseArray<T>>> {
392 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
395 csr.slice(rows, cols)
396 }
397
398 fn as_any(&self) -> &dyn std::any::Any {
399 self
400 }
401
402 fn find(
403 &self,
404 ) -> (
405 ndarray::Array1<usize>,
406 ndarray::Array1<usize>,
407 ndarray::Array1<T>,
408 ) {
409 match <Self as SymSparseArray<T>>::to_csr(self) {
411 Ok(csr) => csr.find(),
412 Err(_) => (
413 ndarray::Array1::from_vec(Vec::new()),
414 ndarray::Array1::from_vec(Vec::new()),
415 ndarray::Array1::from_vec(Vec::new()),
416 ),
417 }
418 }
419
420 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
421 let selfshape = self.shape();
423 let othershape = other.shape();
424
425 if selfshape != othershape {
426 return Err(crate::error::SparseError::DimensionMismatch {
427 expected: selfshape.0,
428 found: othershape.0,
429 });
430 }
431
432 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
434 let other_csr_box = other.to_csr()?;
435
436 match other_csr_box.as_any().downcast_ref::<CsrArray<T>>() {
438 Some(other_csr) => {
439 let result = self_csr.add(other_csr)?;
441
442 use crate::csr::CsrMatrix;
447
448 let (rows, cols, data) = result.find();
450 let csr_matrix =
451 CsrMatrix::new(data.to_vec(), rows.to_vec(), cols.to_vec(), result.shape())?;
452
453 use crate::sym_csr::SymCsrMatrix;
455 let sym_csr = SymCsrMatrix::from_csr(&csr_matrix)?;
456
457 let sym_csr_array = SymCsrArray::new(sym_csr);
459 Ok(Box::new(sym_csr_array) as Box<dyn SparseArray<T>>)
460 }
461 None => {
462 let self_dense = self.to_array();
464 let other_dense = other.to_array();
465
466 let mut result_dense = ndarray::Array2::zeros(selfshape);
468 for i in 0..selfshape.0 {
469 for j in 0..selfshape.1 {
470 result_dense[[i, j]] = self_dense[[i, j]] + other_dense[[i, j]];
471 }
472 }
473
474 let mut rows = Vec::new();
477 let mut cols = Vec::new();
478 let mut values = Vec::new();
479
480 for i in 0..selfshape.0 {
481 for j in 0..selfshape.1 {
482 let val = result_dense[[i, j]];
483 if val != T::zero() {
484 rows.push(i);
485 cols.push(j);
486 values.push(val);
487 }
488 }
489 }
490
491 let csr = CsrArray::from_triplets(&rows, &cols, &values, selfshape, false)?;
492 Ok(Box::new(csr) as Box<dyn SparseArray<T>>)
493 }
494 }
495 }
496
497 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
498 let selfshape = self.shape();
500 let othershape = other.shape();
501
502 if selfshape != othershape {
503 return Err(crate::error::SparseError::DimensionMismatch {
504 expected: selfshape.0,
505 found: othershape.0,
506 });
507 }
508
509 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
511 let other_csr_box = other.to_csr()?;
512
513 match other_csr_box.as_any().downcast_ref::<CsrArray<T>>() {
515 Some(other_csr) => {
516 let result = self_csr.mul(other_csr)?;
518
519 let (rows, cols, data) = result.find();
524
525 use crate::csr::CsrMatrix;
527 let csr_matrix =
528 CsrMatrix::new(data.to_vec(), rows.to_vec(), cols.to_vec(), result.shape())?;
529
530 use crate::sym_csr::SymCsrMatrix;
532 let sym_csr = SymCsrMatrix::from_csr(&csr_matrix)?;
533
534 let sym_csr_array = SymCsrArray::new(sym_csr);
536 Ok(Box::new(sym_csr_array) as Box<dyn SparseArray<T>>)
537 }
538 None => {
539 let self_dense = self.to_array();
541 let other_dense = other.to_array();
542
543 let mut result_dense = ndarray::Array2::zeros(selfshape);
545 for i in 0..selfshape.0 {
546 for j in 0..selfshape.1 {
547 result_dense[[i, j]] = self_dense[[i, j]] * other_dense[[i, j]];
548 }
549 }
550
551 let mut rows = Vec::new();
554 let mut cols = Vec::new();
555 let mut values = Vec::new();
556
557 for i in 0..selfshape.0 {
558 for j in 0..selfshape.1 {
559 let val = result_dense[[i, j]];
560 if val != T::zero() {
561 rows.push(i);
562 cols.push(j);
563 values.push(val);
564 }
565 }
566 }
567
568 let csr = CsrArray::from_triplets(&rows, &cols, &values, selfshape, false)?;
569 Ok(Box::new(csr) as Box<dyn SparseArray<T>>)
570 }
571 }
572 }
573
574 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
575 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
579 let result = self_csr.dot(other)?;
580
581 Ok(result)
585 }
586
587 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
588 Ok(Box::new(self.clone()))
590 }
591
592 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
593 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
595 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
596 csr_box.to_csc()
597 }
598
599 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
600 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
602 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
603 csr_box.to_dia()
604 }
605
606 fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
607 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
609 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
610 csr_box.to_dok()
611 }
612
613 fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
614 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
616 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
617 csr_box.to_lil()
618 }
619
620 fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
621 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
623 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
624 csr_box.to_bsr()
625 }
626}
627
628impl<T> SparseArray<T> for SymCooArray<T>
630where
631 T: Float
632 + Debug
633 + Copy
634 + 'static
635 + Add<Output = T>
636 + Sub<Output = T>
637 + Mul<Output = T>
638 + Div<Output = T>
639 + scirs2_core::simd_ops::SimdUnifiedOps
640 + Send
641 + Sync,
642{
643 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
644 let coo_array = <Self as SymSparseArray<T>>::to_coo(self)?;
645 Ok(Box::new(coo_array))
646 }
647
648 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
649 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
651 Ok(Box::new(csr))
652 }
653 fn shape(&self) -> (usize, usize) {
654 self.inner().shape()
655 }
656
657 fn nnz(&self) -> usize {
658 self.inner().nnz()
659 }
660
661 fn dtype(&self) -> &str {
662 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
663 "f32"
664 } else {
665 "f64"
666 }
667 }
668
669 fn get(&self, row: usize, col: usize) -> T {
670 self.inner().get(row, col)
671 }
672
673 fn to_array(&self) -> ndarray::Array2<T> {
674 let dense = self.inner().to_dense();
676 let mut array = ndarray::Array2::zeros(self.shape());
677
678 for i in 0..dense.len() {
679 for j in 0..dense[i].len() {
680 array[[i, j]] = dense[i][j];
681 }
682 }
683
684 array
685 }
686
687 fn toarray(&self) -> ndarray::Array2<T> {
688 self.to_array()
689 }
690
691 fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()> {
692 Err(SparseError::NotImplemented(
693 "Setting individual elements in SymCooArray is not supported. Convert to another format first.".to_string()
694 ))
695 }
696
697 fn dot_vector(&self, other: &ndarray::ArrayView1<T>) -> SparseResult<ndarray::Array1<T>> {
698 crate::sym_ops::sym_coo_matvec(self.inner(), other)
700 }
701
702 fn copy(&self) -> Box<dyn SparseArray<T>> {
703 Box::new(self.clone())
704 }
705
706 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
707 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
709 self_csr.sub(other)
710 }
711
712 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
713 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
715 self_csr.div(other)
716 }
717
718 fn eliminate_zeros(&mut self) {
719 }
722
723 fn sort_indices(&mut self) {
724 }
727
728 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
729 match self.to_sym_csr() {
731 Ok(csr) => Box::new(csr),
732 Err(_) => Box::new(self.clone()), }
734 }
735
736 fn has_sorted_indices(&self) -> bool {
737 false
738 }
739
740 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
741 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
743 SparseArray::<T>::sum(&csr, axis)
744 }
745
746 fn max(&self) -> T {
747 match <Self as SymSparseArray<T>>::to_csr(self) {
749 Ok(csr) => SparseArray::<T>::max(&csr),
750 Err(_) => T::nan(), }
752 }
753
754 fn min(&self) -> T {
755 match <Self as SymSparseArray<T>>::to_csr(self) {
757 Ok(csr) => SparseArray::<T>::min(&csr),
758 Err(_) => T::nan(), }
760 }
761
762 fn slice(
763 &self,
764 rows: (usize, usize),
765 cols: (usize, usize),
766 ) -> SparseResult<Box<dyn SparseArray<T>>> {
767 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
769 csr.slice(rows, cols)
770 }
771
772 fn as_any(&self) -> &dyn std::any::Any {
773 self
774 }
775
776 fn find(
777 &self,
778 ) -> (
779 ndarray::Array1<usize>,
780 ndarray::Array1<usize>,
781 ndarray::Array1<T>,
782 ) {
783 match <Self as SymSparseArray<T>>::to_coo(self) {
785 Ok(coo) => coo.find(),
786 Err(_) => (
787 ndarray::Array1::from_vec(Vec::new()),
788 ndarray::Array1::from_vec(Vec::new()),
789 ndarray::Array1::from_vec(Vec::new()),
790 ),
791 }
792 }
793
794 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
795 self.to_sym_csr()?.add(other)
797 }
798
799 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
800 self.to_sym_csr()?.mul(other)
802 }
803
804 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
805 <Self as SymSparseArray<T>>::to_csr(self)?.dot(other)
807 }
808
809 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
810 Ok(Box::new(self.clone()))
812 }
813
814 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
815 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
817 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
818 csr_box.to_csc()
819 }
820
821 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
822 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
824 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
825 csr_box.to_dia()
826 }
827
828 fn to_dok(&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_dok()
833 }
834
835 fn to_lil(&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_lil()
840 }
841
842 fn to_bsr(&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_bsr()
847 }
848}
849
850#[cfg(test)]
851mod tests {
852 use super::*;
853 use crate::sym_csr::{SymCsrArray, SymCsrMatrix};
854
855 fn create_test_sym_csr() -> SymCsrArray<f64> {
857 let data = vec![2.0, 1.0, 2.0, 3.0, 1.0];
868 let indices = vec![0, 0, 1, 1, 2];
869 let indptr = vec![0, 1, 3, 5];
870
871 let sym_matrix = SymCsrMatrix::new(data, indptr, indices, (3, 3)).unwrap();
872 SymCsrArray::new(sym_matrix)
873 }
874
875 #[test]
876 fn test_sym_sparse_array_trait() {
877 let sym_csr = create_test_sym_csr();
878
879 assert_eq!(sym_csr.shape(), (3, 3));
881 assert!(sym_csr.is_symmetric());
882
883 assert_eq!(sym_csr.get(0, 0), 2.0);
885 assert_eq!(sym_csr.get(0, 1), 1.0);
886 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();
894 assert_eq!(sym_coo.shape(), (3, 3));
895 assert!(sym_coo.is_symmetric());
896
897 let csr = SymSparseArray::<f64>::to_csr(&sym_csr).unwrap();
898 assert_eq!(csr.shape(), (3, 3));
899
900 let coo = SymSparseArray::<f64>::to_coo(&sym_csr).unwrap();
901 assert_eq!(coo.shape(), (3, 3));
902
903 let (rows, _cols, _data) = sym_csr.find();
905 assert!(rows.len() > sym_csr.nnz_stored()); }
907
908 #[test]
909 fn test_sym_sparse_array_operations() {
910 let sym_csr = create_test_sym_csr();
911
912 let sym_csr2 = create_test_sym_csr();
914
915 let sum = sym_csr.add(&sym_csr2).unwrap();
917 assert_eq!(sum.shape(), (3, 3));
918 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();
924 assert_eq!(prod.shape(), (3, 3));
925 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();
931 assert_eq!(dot.shape(), (3, 3));
932
933 let trans = sym_csr.transpose().unwrap();
935 assert_eq!(trans.shape(), sym_csr.shape());
936 assert_eq!(SparseArray::get(&*trans, 0, 1), sym_csr.get(0, 1));
937 assert_eq!(SparseArray::get(&*trans, 1, 0), sym_csr.get(1, 0));
938 }
939}