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{
89 fn nnz_stored(&self) -> usize {
90 self.inner().nnz_stored()
91 }
92
93 fn to_csr(&self) -> SparseResult<CsrArray<T>> {
94 self.to_csr_array()
95 }
96
97 fn to_coo(&self) -> SparseResult<CooArray<T>> {
98 let csr_inner = self.inner();
100 let shape = csr_inner.shape;
101
102 let mut rows = Vec::new();
104 let mut cols = Vec::new();
105 let mut data = Vec::new();
106
107 for i in 0..shape.0 {
108 for j_ptr in csr_inner.indptr[i]..csr_inner.indptr[i + 1] {
109 let j = csr_inner.indices[j_ptr];
110 let val = csr_inner.data[j_ptr];
111
112 rows.push(i);
114 cols.push(j);
115 data.push(val);
116
117 if i != j {
119 rows.push(j);
120 cols.push(i);
121 data.push(val);
122 }
123 }
124 }
125
126 CooArray::from_triplets(&rows, &cols, &data, shape, false)
128 }
129
130 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>> {
131 Ok(self.clone())
133 }
134
135 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>> {
136 let csr_inner = self.inner();
138
139 let mut data = Vec::new();
141 let mut rows = Vec::new();
142 let mut cols = Vec::new();
143
144 for i in 0..csr_inner.shape.0 {
145 for j in csr_inner.indptr[i]..csr_inner.indptr[i + 1] {
146 let col = csr_inner.indices[j];
147 let val = csr_inner.data[j];
148
149 data.push(val);
150 rows.push(i);
151 cols.push(col);
152 }
153 }
154
155 use crate::sym_coo::SymCooMatrix;
156 let sym_coo = SymCooMatrix::new(data, rows, cols, csr_inner.shape)?;
157
158 Ok(SymCooArray::new(sym_coo))
159 }
160}
161
162impl<T> SymSparseArray<T> for SymCooArray<T>
164where
165 T: Float
166 + Debug
167 + Copy
168 + 'static
169 + Add<Output = T>
170 + Sub<Output = T>
171 + Mul<Output = T>
172 + Div<Output = T>,
173{
174 fn nnz_stored(&self) -> usize {
175 self.inner().nnz_stored()
176 }
177
178 fn to_csr(&self) -> SparseResult<CsrArray<T>> {
179 let coo = self.to_coo_array()?;
181 match coo.to_csr() {
182 Ok(boxed_csr) => {
183 match boxed_csr.as_any().downcast_ref::<CsrArray<T>>() {
185 Some(csr_array) => Ok(csr_array.clone()),
186 None => Err(SparseError::ConversionError(
187 "Failed to downcast to CsrArray".to_string(),
188 )),
189 }
190 }
191 Err(e) => Err(e),
192 }
193 }
194
195 fn to_coo(&self) -> SparseResult<CooArray<T>> {
196 self.to_coo_array()
197 }
198
199 fn to_sym_csr(&self) -> SparseResult<SymCsrArray<T>> {
200 let coo_inner = self.inner();
203
204 let data = coo_inner.data.clone();
206 let rows = coo_inner.rows.clone();
207 let cols = coo_inner.cols.clone();
208 let shape = coo_inner.shape;
209
210 let csr = crate::csr::CsrMatrix::new(data, rows, cols, shape)?;
212
213 use crate::sym_csr::SymCsrMatrix;
215
216 let mut sym_data = Vec::new();
218 let mut sym_indices = Vec::new();
219 let mut sym_indptr = vec![0];
220 let n = shape.0;
221
222 for i in 0..n {
223 for j_ptr in csr.indptr[i]..csr.indptr[i + 1] {
224 let j = csr.indices[j_ptr];
225 let val = csr.data[j_ptr];
226
227 if j <= i {
229 sym_data.push(val);
230 sym_indices.push(j);
231 }
232 }
233
234 sym_indptr.push(sym_data.len());
235 }
236
237 let sym_csr = SymCsrMatrix::new(sym_data, sym_indptr, sym_indices, shape)?;
238
239 Ok(SymCsrArray::new(sym_csr))
240 }
241
242 fn to_sym_coo(&self) -> SparseResult<SymCooArray<T>> {
243 Ok(self.clone())
245 }
246}
247
248impl<T> SparseArray<T> for SymCsrArray<T>
250where
251 T: Float
252 + Debug
253 + Copy
254 + 'static
255 + Add<Output = T>
256 + Sub<Output = T>
257 + Mul<Output = T>
258 + Div<Output = T>,
259{
260 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
261 let coo_array = <Self as SymSparseArray<T>>::to_coo(self)?;
262 Ok(Box::new(coo_array))
263 }
264
265 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
266 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
268 Ok(Box::new(csr))
269 }
270 fn shape(&self) -> (usize, usize) {
271 self.inner().shape()
272 }
273
274 fn nnz(&self) -> usize {
275 self.inner().nnz()
276 }
277
278 fn dtype(&self) -> &str {
279 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
280 "f32"
281 } else {
282 "f64"
283 }
284 }
285
286 fn get(&self, row: usize, col: usize) -> T {
287 self.inner().get(row, col)
288 }
289
290 fn to_array(&self) -> ndarray::Array2<T> {
291 let dense = self.inner().to_dense();
293 let mut array = ndarray::Array2::zeros(self.shape());
294
295 for i in 0..dense.len() {
296 for j in 0..dense[i].len() {
297 array[[i, j]] = dense[i][j];
298 }
299 }
300
301 array
302 }
303
304 fn toarray(&self) -> ndarray::Array2<T> {
305 self.to_array()
306 }
307
308 fn set(&mut self, _i: usize, _j: usize, _value: T) -> SparseResult<()> {
309 Err(SparseError::NotImplemented(
310 "Setting individual elements in SymCsrArray is not supported. Convert to another format first.".to_string()
311 ))
312 }
313
314 fn dot_vector(&self, other: &ndarray::ArrayView1<T>) -> SparseResult<ndarray::Array1<T>> {
315 crate::sym_ops::sym_csr_matvec(self.inner(), other)
317 }
318
319 fn copy(&self) -> Box<dyn SparseArray<T>> {
320 Box::new(self.clone())
321 }
322
323 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
324 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
327 let result = self_csr.sub(other)?;
328
329 Ok(result)
331 }
332
333 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
334 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
336 self_csr.div(other)
337 }
338
339 fn eliminate_zeros(&mut self) {
340 }
342
343 fn sort_indices(&mut self) {
344 }
346
347 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
348 Box::new(self.clone())
350 }
351
352 fn has_sorted_indices(&self) -> bool {
353 true
354 }
355
356 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
357 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
359 SparseArray::<T>::sum(&csr, axis)
360 }
361
362 fn max(&self) -> T {
363 match <Self as SymSparseArray<T>>::to_csr(self) {
365 Ok(csr) => SparseArray::<T>::max(&csr),
366 Err(_) => T::nan(), }
368 }
369
370 fn min(&self) -> T {
371 match <Self as SymSparseArray<T>>::to_csr(self) {
373 Ok(csr) => SparseArray::<T>::min(&csr),
374 Err(_) => T::nan(), }
376 }
377
378 fn slice(
379 &self,
380 rows: (usize, usize),
381 cols: (usize, usize),
382 ) -> SparseResult<Box<dyn SparseArray<T>>> {
383 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
386 csr.slice(rows, cols)
387 }
388
389 fn as_any(&self) -> &dyn std::any::Any {
390 self
391 }
392
393 fn find(
394 &self,
395 ) -> (
396 ndarray::Array1<usize>,
397 ndarray::Array1<usize>,
398 ndarray::Array1<T>,
399 ) {
400 match <Self as SymSparseArray<T>>::to_csr(self) {
402 Ok(csr) => csr.find(),
403 Err(_) => (
404 ndarray::Array1::from_vec(Vec::new()),
405 ndarray::Array1::from_vec(Vec::new()),
406 ndarray::Array1::from_vec(Vec::new()),
407 ),
408 }
409 }
410
411 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
412 let self_shape = self.shape();
414 let other_shape = other.shape();
415
416 if self_shape != other_shape {
417 return Err(crate::error::SparseError::DimensionMismatch {
418 expected: self_shape.0,
419 found: other_shape.0,
420 });
421 }
422
423 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
425 let other_csr_box = other.to_csr()?;
426
427 match other_csr_box.as_any().downcast_ref::<CsrArray<T>>() {
429 Some(other_csr) => {
430 let result = self_csr.add(other_csr)?;
432
433 use crate::csr::CsrMatrix;
438
439 let (rows, cols, data) = result.find();
441 let csr_matrix =
442 CsrMatrix::new(data.to_vec(), rows.to_vec(), cols.to_vec(), result.shape())?;
443
444 use crate::sym_csr::SymCsrMatrix;
446 let sym_csr = SymCsrMatrix::from_csr(&csr_matrix)?;
447
448 let sym_csr_array = SymCsrArray::new(sym_csr);
450 Ok(Box::new(sym_csr_array) as Box<dyn SparseArray<T>>)
451 }
452 None => {
453 let self_dense = self.to_array();
455 let other_dense = other.to_array();
456
457 let mut result_dense = ndarray::Array2::zeros(self_shape);
459 for i in 0..self_shape.0 {
460 for j in 0..self_shape.1 {
461 result_dense[[i, j]] = self_dense[[i, j]] + other_dense[[i, j]];
462 }
463 }
464
465 let mut rows = Vec::new();
468 let mut cols = Vec::new();
469 let mut values = Vec::new();
470
471 for i in 0..self_shape.0 {
472 for j in 0..self_shape.1 {
473 let val = result_dense[[i, j]];
474 if val != T::zero() {
475 rows.push(i);
476 cols.push(j);
477 values.push(val);
478 }
479 }
480 }
481
482 let csr = CsrArray::from_triplets(&rows, &cols, &values, self_shape, false)?;
483 Ok(Box::new(csr) as Box<dyn SparseArray<T>>)
484 }
485 }
486 }
487
488 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
489 let self_shape = self.shape();
491 let other_shape = other.shape();
492
493 if self_shape != other_shape {
494 return Err(crate::error::SparseError::DimensionMismatch {
495 expected: self_shape.0,
496 found: other_shape.0,
497 });
498 }
499
500 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
502 let other_csr_box = other.to_csr()?;
503
504 match other_csr_box.as_any().downcast_ref::<CsrArray<T>>() {
506 Some(other_csr) => {
507 let result = self_csr.mul(other_csr)?;
509
510 let (rows, cols, data) = result.find();
515
516 use crate::csr::CsrMatrix;
518 let csr_matrix =
519 CsrMatrix::new(data.to_vec(), rows.to_vec(), cols.to_vec(), result.shape())?;
520
521 use crate::sym_csr::SymCsrMatrix;
523 let sym_csr = SymCsrMatrix::from_csr(&csr_matrix)?;
524
525 let sym_csr_array = SymCsrArray::new(sym_csr);
527 Ok(Box::new(sym_csr_array) as Box<dyn SparseArray<T>>)
528 }
529 None => {
530 let self_dense = self.to_array();
532 let other_dense = other.to_array();
533
534 let mut result_dense = ndarray::Array2::zeros(self_shape);
536 for i in 0..self_shape.0 {
537 for j in 0..self_shape.1 {
538 result_dense[[i, j]] = self_dense[[i, j]] * other_dense[[i, j]];
539 }
540 }
541
542 let mut rows = Vec::new();
545 let mut cols = Vec::new();
546 let mut values = Vec::new();
547
548 for i in 0..self_shape.0 {
549 for j in 0..self_shape.1 {
550 let val = result_dense[[i, j]];
551 if val != T::zero() {
552 rows.push(i);
553 cols.push(j);
554 values.push(val);
555 }
556 }
557 }
558
559 let csr = CsrArray::from_triplets(&rows, &cols, &values, self_shape, false)?;
560 Ok(Box::new(csr) as Box<dyn SparseArray<T>>)
561 }
562 }
563 }
564
565 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
566 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
570 let result = self_csr.dot(other)?;
571
572 Ok(result)
576 }
577
578 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
579 Ok(Box::new(self.clone()))
581 }
582
583 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
584 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
586 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
587 csr_box.to_csc()
588 }
589
590 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
591 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
593 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
594 csr_box.to_dia()
595 }
596
597 fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
598 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
600 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
601 csr_box.to_dok()
602 }
603
604 fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
605 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
607 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
608 csr_box.to_lil()
609 }
610
611 fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
612 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
614 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
615 csr_box.to_bsr()
616 }
617}
618
619impl<T> SparseArray<T> for SymCooArray<T>
621where
622 T: Float
623 + Debug
624 + Copy
625 + 'static
626 + Add<Output = T>
627 + Sub<Output = T>
628 + Mul<Output = T>
629 + Div<Output = T>,
630{
631 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
632 let coo_array = <Self as SymSparseArray<T>>::to_coo(self)?;
633 Ok(Box::new(coo_array))
634 }
635
636 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
637 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
639 Ok(Box::new(csr))
640 }
641 fn shape(&self) -> (usize, usize) {
642 self.inner().shape()
643 }
644
645 fn nnz(&self) -> usize {
646 self.inner().nnz()
647 }
648
649 fn dtype(&self) -> &str {
650 if std::any::TypeId::of::<T>() == std::any::TypeId::of::<f32>() {
651 "f32"
652 } else {
653 "f64"
654 }
655 }
656
657 fn get(&self, row: usize, col: usize) -> T {
658 self.inner().get(row, col)
659 }
660
661 fn to_array(&self) -> ndarray::Array2<T> {
662 let dense = self.inner().to_dense();
664 let mut array = ndarray::Array2::zeros(self.shape());
665
666 for i in 0..dense.len() {
667 for j in 0..dense[i].len() {
668 array[[i, j]] = dense[i][j];
669 }
670 }
671
672 array
673 }
674
675 fn toarray(&self) -> ndarray::Array2<T> {
676 self.to_array()
677 }
678
679 fn set(&mut self, _i: usize, _j: usize, _value: T) -> SparseResult<()> {
680 Err(SparseError::NotImplemented(
681 "Setting individual elements in SymCooArray is not supported. Convert to another format first.".to_string()
682 ))
683 }
684
685 fn dot_vector(&self, other: &ndarray::ArrayView1<T>) -> SparseResult<ndarray::Array1<T>> {
686 crate::sym_ops::sym_coo_matvec(self.inner(), other)
688 }
689
690 fn copy(&self) -> Box<dyn SparseArray<T>> {
691 Box::new(self.clone())
692 }
693
694 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
695 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
697 self_csr.sub(other)
698 }
699
700 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
701 let self_csr = <Self as SymSparseArray<T>>::to_csr(self)?;
703 self_csr.div(other)
704 }
705
706 fn eliminate_zeros(&mut self) {
707 }
710
711 fn sort_indices(&mut self) {
712 }
715
716 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
717 match self.to_sym_csr() {
719 Ok(csr) => Box::new(csr),
720 Err(_) => Box::new(self.clone()), }
722 }
723
724 fn has_sorted_indices(&self) -> bool {
725 false
726 }
727
728 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
729 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
731 SparseArray::<T>::sum(&csr, axis)
732 }
733
734 fn max(&self) -> T {
735 match <Self as SymSparseArray<T>>::to_csr(self) {
737 Ok(csr) => SparseArray::<T>::max(&csr),
738 Err(_) => T::nan(), }
740 }
741
742 fn min(&self) -> T {
743 match <Self as SymSparseArray<T>>::to_csr(self) {
745 Ok(csr) => SparseArray::<T>::min(&csr),
746 Err(_) => T::nan(), }
748 }
749
750 fn slice(
751 &self,
752 rows: (usize, usize),
753 cols: (usize, usize),
754 ) -> SparseResult<Box<dyn SparseArray<T>>> {
755 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
757 csr.slice(rows, cols)
758 }
759
760 fn as_any(&self) -> &dyn std::any::Any {
761 self
762 }
763
764 fn find(
765 &self,
766 ) -> (
767 ndarray::Array1<usize>,
768 ndarray::Array1<usize>,
769 ndarray::Array1<T>,
770 ) {
771 match <Self as SymSparseArray<T>>::to_coo(self) {
773 Ok(coo) => coo.find(),
774 Err(_) => (
775 ndarray::Array1::from_vec(Vec::new()),
776 ndarray::Array1::from_vec(Vec::new()),
777 ndarray::Array1::from_vec(Vec::new()),
778 ),
779 }
780 }
781
782 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
783 self.to_sym_csr()?.add(other)
785 }
786
787 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
788 self.to_sym_csr()?.mul(other)
790 }
791
792 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
793 <Self as SymSparseArray<T>>::to_csr(self)?.dot(other)
795 }
796
797 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
798 Ok(Box::new(self.clone()))
800 }
801
802 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
803 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
805 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
806 csr_box.to_csc()
807 }
808
809 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
810 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
812 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
813 csr_box.to_dia()
814 }
815
816 fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
817 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
819 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
820 csr_box.to_dok()
821 }
822
823 fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
824 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
826 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
827 csr_box.to_lil()
828 }
829
830 fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
831 let csr = <Self as SymSparseArray<T>>::to_csr(self)?;
833 let csr_box: Box<dyn SparseArray<T>> = Box::new(csr);
834 csr_box.to_bsr()
835 }
836}
837
838#[cfg(test)]
839mod tests {
840 use super::*;
841 use crate::sym_csr::{SymCsrArray, SymCsrMatrix};
842
843 fn create_test_sym_csr() -> SymCsrArray<f64> {
845 let data = vec![2.0, 1.0, 2.0, 3.0, 1.0];
856 let indices = vec![0, 0, 1, 1, 2];
857 let indptr = vec![0, 1, 3, 5];
858
859 let sym_matrix = SymCsrMatrix::new(data, indptr, indices, (3, 3)).unwrap();
860 SymCsrArray::new(sym_matrix)
861 }
862
863 #[test]
864 fn test_sym_sparse_array_trait() {
865 let sym_csr = create_test_sym_csr();
866
867 assert_eq!(sym_csr.shape(), (3, 3));
869 assert!(sym_csr.is_symmetric());
870
871 assert_eq!(sym_csr.get(0, 0), 2.0);
873 assert_eq!(sym_csr.get(0, 1), 1.0);
874 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();
882 assert_eq!(sym_coo.shape(), (3, 3));
883 assert!(sym_coo.is_symmetric());
884
885 let csr = SymSparseArray::<f64>::to_csr(&sym_csr).unwrap();
886 assert_eq!(csr.shape(), (3, 3));
887
888 let coo = SymSparseArray::<f64>::to_coo(&sym_csr).unwrap();
889 assert_eq!(coo.shape(), (3, 3));
890
891 let (rows, _cols, _data) = sym_csr.find();
893 assert!(rows.len() > sym_csr.nnz_stored()); }
895
896 #[test]
897 fn test_sym_sparse_array_operations() {
898 let sym_csr = create_test_sym_csr();
899
900 let sym_csr2 = create_test_sym_csr();
902
903 let sum = sym_csr.add(&sym_csr2).unwrap();
905 assert_eq!(sum.shape(), (3, 3));
906 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();
912 assert_eq!(prod.shape(), (3, 3));
913 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();
919 assert_eq!(dot.shape(), (3, 3));
920
921 let trans = sym_csr.transpose().unwrap();
923 assert_eq!(trans.shape(), sym_csr.shape());
924 assert_eq!(SparseArray::get(&*trans, 0, 1), sym_csr.get(0, 1));
925 assert_eq!(SparseArray::get(&*trans, 1, 0), sym_csr.get(1, 0));
926 }
927}