1use scirs2_core::ndarray::{Array1, Array2, ArrayView1};
7use scirs2_core::numeric::{Float, SparseElement};
8use std::any::Any;
9use std::collections::HashMap;
10use std::fmt::Debug;
11use std::ops::{Add, Div, Mul, Sub};
12
13use crate::coo_array::CooArray;
14use crate::error::{SparseError, SparseResult};
15use crate::lil_array::LilArray;
16use crate::sparray::{SparseArray, SparseSum};
17
18#[derive(Clone)]
32pub struct DokArray<T>
33where
34 T: SparseElement + Div<Output = T> + 'static,
35{
36 data: HashMap<(usize, usize), T>,
38 shape: (usize, usize),
40}
41
42impl<T> DokArray<T>
43where
44 T: SparseElement + Div<Output = T> + 'static,
45{
46 pub fn new(shape: (usize, usize)) -> Self {
54 Self {
55 data: HashMap::new(),
56 shape,
57 }
58 }
59
60 pub fn from_triplets(
74 rows: &[usize],
75 cols: &[usize],
76 data: &[T],
77 shape: (usize, usize),
78 ) -> SparseResult<Self> {
79 if rows.len() != cols.len() || rows.len() != data.len() {
80 return Err(SparseError::InconsistentData {
81 reason: "rows, cols, and data must have the same length".to_string(),
82 });
83 }
84
85 let mut dok = Self::new(shape);
86 for i in 0..rows.len() {
87 if rows[i] >= shape.0 || cols[i] >= shape.1 {
88 return Err(SparseError::IndexOutOfBounds {
89 index: (rows[i], cols[i]),
90 shape,
91 });
92 }
93 if !SparseElement::is_zero(&data[i]) {
95 dok.data.insert((rows[i], cols[i]), data[i]);
96 }
97 }
98
99 Ok(dok)
100 }
101
102 pub fn get_data(&self) -> &HashMap<(usize, usize), T> {
104 &self.data
105 }
106
107 pub fn to_triplets(&self) -> (Array1<usize>, Array1<usize>, Array1<T>)
109 where
110 T: Float + PartialOrd,
111 {
112 let nnz = self.nnz();
113 let mut row_indices = Vec::with_capacity(nnz);
114 let mut col_indices = Vec::with_capacity(nnz);
115 let mut values = Vec::with_capacity(nnz);
116
117 let mut entries: Vec<_> = self.data.iter().collect();
119 entries.sort_by_key(|(&(row, col), _)| (row, col));
120
121 for (&(row, col), &value) in entries {
122 row_indices.push(row);
123 col_indices.push(col);
124 values.push(value);
125 }
126
127 (
128 Array1::from_vec(row_indices),
129 Array1::from_vec(col_indices),
130 Array1::from_vec(values),
131 )
132 }
133
134 pub fn from_array(array: &Array2<T>) -> Self {
142 let shape = (array.shape()[0], array.shape()[1]);
143 let mut dok = Self::new(shape);
144
145 for ((i, j), &value) in array.indexed_iter() {
146 if !SparseElement::is_zero(&value) {
147 dok.data.insert((i, j), value);
148 }
149 }
150
151 dok
152 }
153}
154
155impl<T> SparseArray<T> for DokArray<T>
156where
157 T: SparseElement + Div<Output = T> + Float + PartialOrd + 'static,
158{
159 fn shape(&self) -> (usize, usize) {
160 self.shape
161 }
162
163 fn nnz(&self) -> usize {
164 self.data.len()
165 }
166
167 fn dtype(&self) -> &str {
168 std::any::type_name::<T>()
169 }
170
171 fn to_array(&self) -> Array2<T> {
172 let (rows, cols) = self.shape;
173 let mut result = Array2::zeros((rows, cols));
174
175 for (&(row, col), &value) in &self.data {
176 result[[row, col]] = value;
177 }
178
179 result
180 }
181
182 fn toarray(&self) -> Array2<T> {
183 self.to_array()
184 }
185
186 fn to_coo(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
187 let (row_indices, col_indices, data) = self.to_triplets();
188 CooArray::new(data, row_indices, col_indices, self.shape, true)
189 .map(|array| Box::new(array) as Box<dyn SparseArray<T>>)
190 }
191
192 fn to_csr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
193 match self.to_coo() {
195 Ok(coo) => coo.to_csr(),
196 Err(e) => Err(e),
197 }
198 }
199
200 fn to_csc(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
201 match self.to_coo() {
203 Ok(coo) => coo.to_csc(),
204 Err(e) => Err(e),
205 }
206 }
207
208 fn to_dok(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
209 Ok(Box::new(self.clone()))
211 }
212
213 fn to_lil(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
214 let (rows_arr, cols_arr, vals_arr) = self.to_triplets();
215 let rows_slice = rows_arr
216 .as_slice()
217 .ok_or_else(|| SparseError::ValueError("non-contiguous row indices".to_string()))?;
218 let cols_slice = cols_arr
219 .as_slice()
220 .ok_or_else(|| SparseError::ValueError("non-contiguous col indices".to_string()))?;
221 let vals_slice = vals_arr
222 .as_slice()
223 .ok_or_else(|| SparseError::ValueError("non-contiguous values".to_string()))?;
224 let lil = LilArray::from_triplets(rows_slice, cols_slice, vals_slice, self.shape)?;
225 Ok(Box::new(lil))
226 }
227
228 fn to_dia(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
229 self.to_csr()?.to_dia()
230 }
231
232 fn to_bsr(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
233 self.to_csr()?.to_bsr()
234 }
235
236 fn add(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
237 if self.shape() != other.shape() {
238 return Err(SparseError::DimensionMismatch {
239 expected: self.shape().0,
240 found: other.shape().0,
241 });
242 }
243
244 let mut result = self.clone();
245 let other_array = other.to_array();
246
247 for (&(row, col), &value) in &self.data {
249 result.set(row, col, value + other_array[[row, col]])?;
250 }
251
252 for ((row, col), &value) in other_array.indexed_iter() {
254 if !self.data.contains_key(&(row, col)) && !SparseElement::is_zero(&value) {
255 result.set(row, col, value)?;
256 }
257 }
258
259 Ok(Box::new(result))
260 }
261
262 fn sub(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
263 if self.shape() != other.shape() {
264 return Err(SparseError::DimensionMismatch {
265 expected: self.shape().0,
266 found: other.shape().0,
267 });
268 }
269
270 let mut result = self.clone();
271 let other_array = other.to_array();
272
273 for (&(row, col), &value) in &self.data {
275 result.set(row, col, value - other_array[[row, col]])?;
276 }
277
278 for ((row, col), &value) in other_array.indexed_iter() {
280 if !self.data.contains_key(&(row, col)) && !SparseElement::is_zero(&value) {
281 result.set(row, col, -value)?;
282 }
283 }
284
285 Ok(Box::new(result))
286 }
287
288 fn mul(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
289 if self.shape() != other.shape() {
290 return Err(SparseError::DimensionMismatch {
291 expected: self.shape().0,
292 found: other.shape().0,
293 });
294 }
295
296 let mut result = DokArray::new(self.shape());
297 let other_array = other.to_array();
298
299 for (&(row, col), &value) in &self.data {
302 let product = value * other_array[[row, col]];
303 if !SparseElement::is_zero(&product) {
304 result.set(row, col, product)?;
305 }
306 }
307
308 Ok(Box::new(result))
309 }
310
311 fn div(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
312 if self.shape() != other.shape() {
313 return Err(SparseError::DimensionMismatch {
314 expected: self.shape().0,
315 found: other.shape().0,
316 });
317 }
318
319 let mut result = DokArray::new(self.shape());
320 let other_array = other.to_array();
321
322 for (&(row, col), &value) in &self.data {
323 let divisor = other_array[[row, col]];
324 if SparseElement::is_zero(&divisor) {
325 return Err(SparseError::ComputationError(
326 "Division by zero".to_string(),
327 ));
328 }
329
330 let quotient = value / divisor;
331 if !SparseElement::is_zero("ient) {
332 result.set(row, col, quotient)?;
333 }
334 }
335
336 Ok(Box::new(result))
337 }
338
339 fn dot(&self, other: &dyn SparseArray<T>) -> SparseResult<Box<dyn SparseArray<T>>> {
340 let (_m, n) = self.shape();
341 let (p, q) = other.shape();
342
343 if n != p {
344 return Err(SparseError::DimensionMismatch {
345 expected: n,
346 found: p,
347 });
348 }
349
350 let csr_self = self.to_csr()?;
352 let csr_other = other.to_csr()?;
353
354 csr_self.dot(&*csr_other)
355 }
356
357 fn dot_vector(&self, other: &ArrayView1<T>) -> SparseResult<Array1<T>> {
358 let (m, n) = self.shape();
359 if n != other.len() {
360 return Err(SparseError::DimensionMismatch {
361 expected: n,
362 found: other.len(),
363 });
364 }
365
366 let mut result = Array1::zeros(m);
367
368 for (&(row, col), &value) in &self.data {
369 result[row] = result[row] + value * other[col];
370 }
371
372 Ok(result)
373 }
374
375 fn transpose(&self) -> SparseResult<Box<dyn SparseArray<T>>> {
376 let (rows, cols) = self.shape;
377 let mut result = DokArray::new((cols, rows));
378
379 for (&(row, col), &value) in &self.data {
380 result.set(col, row, value)?;
381 }
382
383 Ok(Box::new(result))
384 }
385
386 fn copy(&self) -> Box<dyn SparseArray<T>> {
387 Box::new(self.clone())
388 }
389
390 fn get(&self, i: usize, j: usize) -> T {
391 if i >= self.shape.0 || j >= self.shape.1 {
392 return T::sparse_zero();
393 }
394
395 *self.data.get(&(i, j)).unwrap_or(&T::sparse_zero())
396 }
397
398 fn set(&mut self, i: usize, j: usize, value: T) -> SparseResult<()> {
399 if i >= self.shape.0 || j >= self.shape.1 {
400 return Err(SparseError::IndexOutOfBounds {
401 index: (i, j),
402 shape: self.shape,
403 });
404 }
405
406 if SparseElement::is_zero(&value) {
407 self.data.remove(&(i, j));
409 } else {
410 self.data.insert((i, j), value);
412 }
413
414 Ok(())
415 }
416
417 fn eliminate_zeros(&mut self) {
418 self.data
420 .retain(|_, &mut value| !SparseElement::is_zero(&value));
421 }
422
423 fn sort_indices(&mut self) {
424 }
426
427 fn sorted_indices(&self) -> Box<dyn SparseArray<T>> {
428 self.copy()
430 }
431
432 fn has_sorted_indices(&self) -> bool {
433 true }
435
436 fn sum(&self, axis: Option<usize>) -> SparseResult<SparseSum<T>> {
437 match axis {
438 None => {
439 let mut sum = T::sparse_zero();
441 for &value in self.data.values() {
442 sum = sum + value;
443 }
444 Ok(SparseSum::Scalar(sum))
445 }
446 Some(0) => {
447 let (_, cols) = self.shape();
449 let mut result = DokArray::new((1, cols));
450
451 for (&(_row, col), &value) in &self.data {
452 let current = result.get(0, col);
453 result.set(0, col, current + value)?;
454 }
455
456 Ok(SparseSum::SparseArray(Box::new(result)))
457 }
458 Some(1) => {
459 let (rows, _) = self.shape();
461 let mut result = DokArray::new((rows, 1));
462
463 for (&(row, col), &value) in &self.data {
464 let current = result.get(row, 0);
465 result.set(row, 0, current + value)?;
466 }
467
468 Ok(SparseSum::SparseArray(Box::new(result)))
469 }
470 _ => Err(SparseError::InvalidAxis),
471 }
472 }
473
474 fn max(&self) -> T {
475 if self.data.is_empty() {
476 return T::nan();
477 }
478
479 self.data
480 .values()
481 .fold(T::neg_infinity(), |acc, &x| acc.max(x))
482 }
483
484 fn min(&self) -> T {
485 if self.data.is_empty() {
486 return T::nan();
487 }
488
489 self.data
490 .values()
491 .fold(T::sparse_zero(), |acc, &x| acc.min(x))
492 }
493
494 fn find(&self) -> (Array1<usize>, Array1<usize>, Array1<T>) {
495 self.to_triplets()
496 }
497
498 fn slice(
499 &self,
500 row_range: (usize, usize),
501 col_range: (usize, usize),
502 ) -> SparseResult<Box<dyn SparseArray<T>>> {
503 let (start_row, end_row) = row_range;
504 let (start_col, end_col) = col_range;
505 let (rows, cols) = self.shape;
506
507 if start_row >= rows
508 || end_row > rows
509 || start_col >= cols
510 || end_col > cols
511 || start_row >= end_row
512 || start_col >= end_col
513 {
514 return Err(SparseError::InvalidSliceRange);
515 }
516
517 let sliceshape = (end_row - start_row, end_col - start_col);
518 let mut result = DokArray::new(sliceshape);
519
520 for (&(row, col), &value) in &self.data {
521 if row >= start_row && row < end_row && col >= start_col && col < end_col {
522 result.set(row - start_row, col - start_col, value)?;
523 }
524 }
525
526 Ok(Box::new(result))
527 }
528
529 fn as_any(&self) -> &dyn Any {
530 self
531 }
532}
533
534#[cfg(test)]
535mod tests {
536 use super::*;
537 use scirs2_core::ndarray::Array;
538
539 #[test]
540 fn test_dok_array_dtype_reflects_actual_element_type() {
541 let dok_f64 = DokArray::<f64>::new((2, 2));
542 let dok_f32 = DokArray::<f32>::new((2, 2));
543
544 assert_eq!(dok_f64.dtype(), "f64");
547 assert_eq!(dok_f32.dtype(), "f32");
548 assert_ne!(dok_f64.dtype(), "float");
549 assert_ne!(dok_f32.dtype(), dok_f64.dtype());
550 }
551
552 #[test]
553 fn test_dok_array_create_and_access() {
554 let mut array = DokArray::<f64>::new((3, 3));
556
557 array
559 .set(0, 0, 1.0)
560 .expect("Test: failed to set array element");
561 array
562 .set(0, 2, 2.0)
563 .expect("Test: failed to set array element");
564 array
565 .set(1, 2, 3.0)
566 .expect("Test: failed to set array element");
567 array
568 .set(2, 0, 4.0)
569 .expect("Test: failed to set array element");
570 array
571 .set(2, 1, 5.0)
572 .expect("Test: failed to set array element");
573
574 assert_eq!(array.nnz(), 5);
575
576 assert_eq!(array.get(0, 0), 1.0);
578 assert_eq!(array.get(0, 1), 0.0); assert_eq!(array.get(0, 2), 2.0);
580 assert_eq!(array.get(1, 2), 3.0);
581 assert_eq!(array.get(2, 0), 4.0);
582 assert_eq!(array.get(2, 1), 5.0);
583
584 array
586 .set(0, 0, 0.0)
587 .expect("Test: failed to set array element");
588 assert_eq!(array.nnz(), 4);
589 assert_eq!(array.get(0, 0), 0.0);
590
591 assert_eq!(array.get(3, 0), 0.0);
593 assert_eq!(array.get(0, 3), 0.0);
594 }
595
596 #[test]
597 fn test_dok_array_from_triplets() {
598 let rows = vec![0, 0, 1, 2, 2];
599 let cols = vec![0, 2, 2, 0, 1];
600 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
601
602 let array = DokArray::from_triplets(&rows, &cols, &data, (3, 3))
603 .expect("Test: failed to create DokArray from triplets");
604
605 assert_eq!(array.nnz(), 5);
606 assert_eq!(array.get(0, 0), 1.0);
607 assert_eq!(array.get(0, 2), 2.0);
608 assert_eq!(array.get(1, 2), 3.0);
609 assert_eq!(array.get(2, 0), 4.0);
610 assert_eq!(array.get(2, 1), 5.0);
611 }
612
613 #[test]
614 fn test_dok_array_to_array() {
615 let rows = vec![0, 0, 1, 2, 2];
616 let cols = vec![0, 2, 2, 0, 1];
617 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
618
619 let array = DokArray::from_triplets(&rows, &cols, &data, (3, 3))
620 .expect("Test: failed to create DokArray from triplets");
621 let dense = array.to_array();
622
623 let expected =
624 Array::from_shape_vec((3, 3), vec![1.0, 0.0, 2.0, 0.0, 0.0, 3.0, 4.0, 5.0, 0.0])
625 .expect("Test: failed to create array from shape vec");
626
627 assert_eq!(dense, expected);
628 }
629
630 #[test]
631 fn test_dok_array_from_array() {
632 let dense =
633 Array::from_shape_vec((3, 3), vec![1.0, 0.0, 2.0, 0.0, 0.0, 3.0, 4.0, 5.0, 0.0])
634 .expect("Test: failed to create array from shape vec");
635
636 let array = DokArray::from_array(&dense);
637
638 assert_eq!(array.nnz(), 5);
639 assert_eq!(array.get(0, 0), 1.0);
640 assert_eq!(array.get(0, 2), 2.0);
641 assert_eq!(array.get(1, 2), 3.0);
642 assert_eq!(array.get(2, 0), 4.0);
643 assert_eq!(array.get(2, 1), 5.0);
644 }
645
646 #[test]
647 fn test_dok_array_add() {
648 let mut array1 = DokArray::<f64>::new((2, 2));
649 array1
650 .set(0, 0, 1.0)
651 .expect("Test: failed to set array element");
652 array1
653 .set(0, 1, 2.0)
654 .expect("Test: failed to set array element");
655 array1
656 .set(1, 0, 3.0)
657 .expect("Test: failed to set array element");
658
659 let mut array2 = DokArray::<f64>::new((2, 2));
660 array2
661 .set(0, 0, 4.0)
662 .expect("Test: failed to set array element");
663 array2
664 .set(1, 1, 5.0)
665 .expect("Test: failed to set array element");
666
667 let result = array1.add(&array2).expect("Test: array addition failed");
668 let dense_result = result.to_array();
669
670 assert_eq!(dense_result[[0, 0]], 5.0);
671 assert_eq!(dense_result[[0, 1]], 2.0);
672 assert_eq!(dense_result[[1, 0]], 3.0);
673 assert_eq!(dense_result[[1, 1]], 5.0);
674 }
675
676 #[test]
677 fn test_dok_array_mul() {
678 let mut array1 = DokArray::<f64>::new((2, 2));
679 array1
680 .set(0, 0, 1.0)
681 .expect("Test: failed to set array element");
682 array1
683 .set(0, 1, 2.0)
684 .expect("Test: failed to set array element");
685 array1
686 .set(1, 0, 3.0)
687 .expect("Test: failed to set array element");
688 array1
689 .set(1, 1, 4.0)
690 .expect("Test: failed to set array element");
691
692 let mut array2 = DokArray::<f64>::new((2, 2));
693 array2
694 .set(0, 0, 5.0)
695 .expect("Test: failed to set array element");
696 array2
697 .set(0, 1, 6.0)
698 .expect("Test: failed to set array element");
699 array2
700 .set(1, 0, 7.0)
701 .expect("Test: failed to set array element");
702 array2
703 .set(1, 1, 8.0)
704 .expect("Test: failed to set array element");
705
706 let result = array1
708 .mul(&array2)
709 .expect("Test: array multiplication failed");
710 let dense_result = result.to_array();
711
712 assert_eq!(dense_result[[0, 0]], 5.0);
713 assert_eq!(dense_result[[0, 1]], 12.0);
714 assert_eq!(dense_result[[1, 0]], 21.0);
715 assert_eq!(dense_result[[1, 1]], 32.0);
716 }
717
718 #[test]
719 fn test_dok_array_dot() {
720 let mut array1 = DokArray::<f64>::new((2, 2));
721 array1
722 .set(0, 0, 1.0)
723 .expect("Test: failed to set array element");
724 array1
725 .set(0, 1, 2.0)
726 .expect("Test: failed to set array element");
727 array1
728 .set(1, 0, 3.0)
729 .expect("Test: failed to set array element");
730 array1
731 .set(1, 1, 4.0)
732 .expect("Test: failed to set array element");
733
734 let mut array2 = DokArray::<f64>::new((2, 2));
735 array2
736 .set(0, 0, 5.0)
737 .expect("Test: failed to set array element");
738 array2
739 .set(0, 1, 6.0)
740 .expect("Test: failed to set array element");
741 array2
742 .set(1, 0, 7.0)
743 .expect("Test: failed to set array element");
744 array2
745 .set(1, 1, 8.0)
746 .expect("Test: failed to set array element");
747
748 let result = array1.dot(&array2).expect("Test: array dot product failed");
750 let dense_result = result.to_array();
751
752 assert_eq!(dense_result[[0, 0]], 19.0);
755 assert_eq!(dense_result[[0, 1]], 22.0);
756 assert_eq!(dense_result[[1, 0]], 43.0);
757 assert_eq!(dense_result[[1, 1]], 50.0);
758 }
759
760 #[test]
761 fn test_dok_array_transpose() {
762 let mut array = DokArray::<f64>::new((2, 3));
763 array
764 .set(0, 0, 1.0)
765 .expect("Test: failed to set array element");
766 array
767 .set(0, 1, 2.0)
768 .expect("Test: failed to set array element");
769 array
770 .set(0, 2, 3.0)
771 .expect("Test: failed to set array element");
772 array
773 .set(1, 0, 4.0)
774 .expect("Test: failed to set array element");
775 array
776 .set(1, 1, 5.0)
777 .expect("Test: failed to set array element");
778 array
779 .set(1, 2, 6.0)
780 .expect("Test: failed to set array element");
781
782 let transposed = array.transpose().expect("Test: array transpose failed");
783
784 assert_eq!(transposed.shape(), (3, 2));
785 assert_eq!(transposed.get(0, 0), 1.0);
786 assert_eq!(transposed.get(1, 0), 2.0);
787 assert_eq!(transposed.get(2, 0), 3.0);
788 assert_eq!(transposed.get(0, 1), 4.0);
789 assert_eq!(transposed.get(1, 1), 5.0);
790 assert_eq!(transposed.get(2, 1), 6.0);
791 }
792
793 #[test]
794 fn test_dok_array_slice() {
795 let mut array = DokArray::<f64>::new((3, 3));
796 array
797 .set(0, 0, 1.0)
798 .expect("Test: failed to set array element");
799 array
800 .set(0, 1, 2.0)
801 .expect("Test: failed to set array element");
802 array
803 .set(0, 2, 3.0)
804 .expect("Test: failed to set array element");
805 array
806 .set(1, 0, 4.0)
807 .expect("Test: failed to set array element");
808 array
809 .set(1, 1, 5.0)
810 .expect("Test: failed to set array element");
811 array
812 .set(1, 2, 6.0)
813 .expect("Test: failed to set array element");
814 array
815 .set(2, 0, 7.0)
816 .expect("Test: failed to set array element");
817 array
818 .set(2, 1, 8.0)
819 .expect("Test: failed to set array element");
820 array
821 .set(2, 2, 9.0)
822 .expect("Test: failed to set array element");
823
824 let slice = array
825 .slice((0, 2), (1, 3))
826 .expect("Test: array slice failed");
827
828 assert_eq!(slice.shape(), (2, 2));
829 assert_eq!(slice.get(0, 0), 2.0);
830 assert_eq!(slice.get(0, 1), 3.0);
831 assert_eq!(slice.get(1, 0), 5.0);
832 assert_eq!(slice.get(1, 1), 6.0);
833 }
834
835 #[test]
836 fn test_dok_array_sum() {
837 let mut array = DokArray::<f64>::new((2, 3));
838 array
839 .set(0, 0, 1.0)
840 .expect("Test: failed to set array element");
841 array
842 .set(0, 1, 2.0)
843 .expect("Test: failed to set array element");
844 array
845 .set(0, 2, 3.0)
846 .expect("Test: failed to set array element");
847 array
848 .set(1, 0, 4.0)
849 .expect("Test: failed to set array element");
850 array
851 .set(1, 1, 5.0)
852 .expect("Test: failed to set array element");
853 array
854 .set(1, 2, 6.0)
855 .expect("Test: failed to set array element");
856
857 match array.sum(None).expect("Test: array sum failed") {
859 SparseSum::Scalar(sum) => assert_eq!(sum, 21.0),
860 _ => panic!("Expected scalar sum"),
861 }
862
863 match array.sum(Some(0)).expect("Test: array sum failed") {
865 SparseSum::SparseArray(sum_array) => {
866 assert_eq!(sum_array.shape(), (1, 3));
867 assert_eq!(sum_array.get(0, 0), 5.0);
868 assert_eq!(sum_array.get(0, 1), 7.0);
869 assert_eq!(sum_array.get(0, 2), 9.0);
870 }
871 _ => panic!("Expected sparse array"),
872 }
873
874 match array.sum(Some(1)).expect("Test: array sum failed") {
876 SparseSum::SparseArray(sum_array) => {
877 assert_eq!(sum_array.shape(), (2, 1));
878 assert_eq!(sum_array.get(0, 0), 6.0);
879 assert_eq!(sum_array.get(1, 0), 15.0);
880 }
881 _ => panic!("Expected sparse array"),
882 }
883 }
884}