1#![allow(clippy::manual_div_ceil)]
2#![allow(clippy::needless_return)]
3#![allow(clippy::manual_ok_err)]
4#![allow(clippy::needless_range_loop)]
5#![allow(clippy::while_let_loop)]
6#![allow(clippy::vec_init_then_push)]
7#![allow(clippy::should_implement_trait)]
8#![allow(clippy::only_used_in_recursion)]
9#![allow(clippy::manual_slice_fill)]
10#![allow(dead_code)]
11pub mod error;
108pub use error::{SparseError, SparseResult};
109
110pub mod sparray;
112pub use sparray::{is_sparse, SparseArray, SparseSum};
113
114pub mod sym_sparray;
116pub use sym_sparray::SymSparseArray;
117
118pub mod csr_array;
122pub use csr_array::CsrArray;
123
124pub mod csc_array;
125pub use csc_array::CscArray;
126
127pub mod coo_array;
128pub use coo_array::CooArray;
129
130pub mod dok_array;
131pub use dok_array::DokArray;
132
133pub mod lil_array;
134pub use lil_array::LilArray;
135
136pub mod dia_array;
137pub use dia_array::DiaArray;
138
139pub mod bsr_array;
140pub use bsr_array::BsrArray;
141
142pub mod banded_array;
143pub use banded_array::BandedArray;
144
145pub mod sym_csr;
147pub use sym_csr::{SymCsrArray, SymCsrMatrix};
148
149pub mod sym_coo;
150pub use sym_coo::{SymCooArray, SymCooMatrix};
151
152pub mod csr;
154pub use csr::CsrMatrix;
155
156pub mod csc;
157pub use csc::CscMatrix;
158
159pub mod coo;
160pub use coo::CooMatrix;
161
162pub mod dok;
163pub use dok::DokMatrix;
164
165pub mod lil;
166pub use lil::LilMatrix;
167
168pub mod dia;
169pub use dia::DiaMatrix;
170
171pub mod bsr;
172pub use bsr::BsrMatrix;
173
174pub mod banded;
175pub use banded::BandedMatrix;
176
177pub mod utils;
179
180pub mod linalg;
182pub use linalg::{
184 add,
186 bicg,
188 bicgstab,
189 cg,
190 cholesky_decomposition,
191 convolution_operator,
193 diag_matrix,
194 eigs,
195 eigsh,
196 enhanced_add,
197 enhanced_diagonal,
198 enhanced_scale,
199 enhanced_subtract,
200 expm,
201 expm_multiply,
203 eye,
204 finite_difference_operator,
205 gcrot,
207 gmres,
208 incomplete_cholesky,
209 incomplete_lu,
210 inv,
211 lanczos,
212 lu_decomposition,
214 matmul,
215 matrix_power,
216 multiply,
217 norm,
218 onenormest,
219 power_iteration,
221 qr_decomposition,
222 solve_arrow_matrix,
224 solve_banded_system,
225 solve_block_2x2,
226 solve_kronecker_system,
227 solve_saddle_point,
228 sparse_direct_solve,
229 sparse_lstsq,
230 spsolve,
231 svd_truncated,
232 svds,
234 tfqmr,
236 ArpackOptions,
237 AsLinearOperator,
239 BiCGOptions,
241 BiCGSTABOptions,
242 BiCGSTABResult,
243 BoundaryCondition,
245 CGOptions,
246 CGSOptions,
247 CGSResult,
248 CholeskyResult,
249 ConvolutionMode,
250 ConvolutionOperator,
251 DiagonalOperator,
253 EigenResult,
254 EigenvalueMethod,
255 EnhancedDiagonalOperator,
256 EnhancedDifferenceOperator,
257 EnhancedOperatorOptions,
258 EnhancedScaledOperator,
259 EnhancedSumOperator,
260 FiniteDifferenceOperator,
261 GCROTOptions,
262 GCROTResult,
263 GMRESOptions,
264 ICOptions,
265 ILU0Preconditioner,
267 ILUOptions,
268 IdentityOperator,
269 IterationResult,
270 JacobiPreconditioner,
271 LUResult,
273 LanczosOptions,
274 LinearOperator,
275 PowerIterationOptions,
277 QRResult,
278 SSORPreconditioner,
279 SVDOptions,
281 SVDResult,
282 ScaledIdentityOperator,
283 TFQMROptions,
284 TFQMRResult,
285};
286
287pub mod convert;
289
290pub mod construct;
292pub mod construct_sym;
293
294pub mod combine;
296pub use combine::{block_diag, bmat, hstack, kron, kronsum, tril, triu, vstack};
297
298pub mod index_dtype;
300pub use index_dtype::{can_cast_safely, get_index_dtype, safely_cast_index_arrays};
301
302pub mod sym_ops;
304
305pub mod tensor_sparse;
307pub use sym_ops::{
308 sym_coo_matvec, sym_csr_matvec, sym_csr_quadratic_form, sym_csr_rank1_update, sym_csr_trace,
309};
310
311pub use tensor_sparse::{khatri_rao_product, CPDecomposition, SparseTensor, TuckerDecomposition};
313
314pub mod gpu;
316pub mod gpu_kernel_execution;
317pub mod gpu_ops;
318pub mod gpu_spmv_implementation;
319pub use gpu_kernel_execution::{
320 calculate_adaptive_workgroup_size, execute_spmv_kernel, execute_symmetric_spmv_kernel,
321 execute_triangular_solve_kernel, GpuKernelConfig, GpuMemoryManager as GpuKernelMemoryManager,
322 GpuPerformanceProfiler, MemoryStrategy,
323};
324pub use gpu_ops::{
325 gpu_sparse_matvec, gpu_sym_sparse_matvec, AdvancedGpuOps, GpuKernelScheduler, GpuMemoryManager,
326 GpuOptions, GpuProfiler, OptimizedGpuOps,
327};
328pub use gpu_spmv_implementation::GpuSpMV;
329
330pub mod memory_efficient;
332pub use memory_efficient::{
333 streaming_sparse_matvec, CacheAwareOps, MemoryPool, MemoryTracker, OutOfCoreProcessor,
334};
335
336pub mod simd_ops;
338pub use simd_ops::{
339 simd_csr_matvec, simd_sparse_elementwise, simd_sparse_linear_combination, simd_sparse_matmul,
340 simd_sparse_norm, simd_sparse_scale, simd_sparse_transpose, ElementwiseOp, SimdOptions,
341};
342
343pub mod parallel_vector_ops;
345pub use parallel_vector_ops::{
346 advanced_sparse_matvec_csr, parallel_axpy, parallel_dot, parallel_linear_combination,
347 parallel_norm2, parallel_sparse_matvec_csr, parallel_vector_add, parallel_vector_copy,
348 parallel_vector_scale, parallel_vector_sub, ParallelVectorOptions,
349};
350
351pub mod quantum_inspired_sparse;
353pub use quantum_inspired_sparse::{
354 QuantumProcessorStats, QuantumSparseConfig, QuantumSparseProcessor, QuantumStrategy,
355};
356
357pub mod neural_adaptive_sparse;
359pub use neural_adaptive_sparse::{
360 NeuralAdaptiveConfig, NeuralAdaptiveSparseProcessor, NeuralProcessorStats, OptimizationStrategy,
361};
362
363pub mod quantum_neural_hybrid;
365pub use quantum_neural_hybrid::{
366 HybridStrategy, QuantumNeuralConfig, QuantumNeuralHybridProcessor, QuantumNeuralHybridStats,
367};
368
369pub mod adaptive_memory_compression;
371pub use adaptive_memory_compression::{
372 AdaptiveCompressionConfig, AdaptiveMemoryCompressor, CompressedMatrix, CompressionAlgorithm,
373 MemoryStats,
374};
375
376pub mod realtime_performance_monitor;
378pub use realtime_performance_monitor::{
379 Alert, AlertSeverity, PerformanceMonitorConfig, PerformanceSample, ProcessorType,
380 RealTimePerformanceMonitor,
381};
382
383pub mod csgraph;
385pub use csgraph::{
386 all_pairs_shortest_path,
387 bellman_ford_single_source,
388 betweenness_centrality,
390 bfs_distances,
391 breadth_first_search,
393 closeness_centrality,
394 community_detection,
396 compute_laplacianmatrix,
397 connected_components,
398 degree_matrix,
399 depth_first_search,
400 dijkstra_single_source,
401 dinic,
403 edmonds_karp,
404 eigenvector_centrality,
405 floyd_warshall,
406 ford_fulkerson,
407 has_path,
408 is_connected,
409 is_laplacian,
410 is_spanning_tree,
411 kruskal_mst,
413 label_propagation,
414 laplacian,
416 largest_component,
417 louvain_communities,
418 min_cut,
419 minimum_spanning_tree,
420 modularity,
421 num_edges,
422 num_vertices,
423 pagerank,
424 prim_mst,
425 reachable_vertices,
426 reconstruct_path,
427 shortest_path,
429 single_source_shortest_path,
431 spanning_tree_weight,
432 strongly_connected_components,
433 to_adjacency_list,
434 topological_sort,
435 traversegraph,
436 undirected_connected_components,
438 validate_graph,
440 weakly_connected_components,
441 LaplacianType,
442 MSTAlgorithm,
443 MaxFlowResult,
445 ShortestPathMethod,
447 TraversalOrder,
448};
449
450pub struct SparseEfficiencyWarning;
452pub struct SparseWarning;
453
454#[allow(dead_code)]
456pub fn is_sparse_array<T>(obj: &dyn SparseArray<T>) -> bool
457where
458 T: scirs2_core::SparseElement + std::ops::Div<Output = T> + PartialOrd + 'static,
459{
460 sparray::is_sparse(obj)
461}
462
463#[allow(dead_code)]
465pub fn is_sym_sparse_array<T>(obj: &dyn SymSparseArray<T>) -> bool
466where
467 T: scirs2_core::SparseElement
468 + std::ops::Div<Output = T>
469 + scirs2_core::Float
470 + PartialOrd
471 + 'static,
472{
473 obj.is_symmetric()
474}
475
476#[allow(dead_code)]
478pub fn is_sparse_matrix(obj: &dyn std::any::Any) -> bool {
479 obj.is::<CsrMatrix<f64>>()
480 || obj.is::<CscMatrix<f64>>()
481 || obj.is::<CooMatrix<f64>>()
482 || obj.is::<DokMatrix<f64>>()
483 || obj.is::<LilMatrix<f64>>()
484 || obj.is::<DiaMatrix<f64>>()
485 || obj.is::<BsrMatrix<f64>>()
486 || obj.is::<SymCsrMatrix<f64>>()
487 || obj.is::<SymCooMatrix<f64>>()
488 || obj.is::<CsrMatrix<f32>>()
489 || obj.is::<CscMatrix<f32>>()
490 || obj.is::<CooMatrix<f32>>()
491 || obj.is::<DokMatrix<f32>>()
492 || obj.is::<LilMatrix<f32>>()
493 || obj.is::<DiaMatrix<f32>>()
494 || obj.is::<BsrMatrix<f32>>()
495 || obj.is::<SymCsrMatrix<f32>>()
496 || obj.is::<SymCooMatrix<f32>>()
497}
498
499#[cfg(test)]
500mod tests {
501 use super::*;
502 use approx::assert_relative_eq;
503
504 #[test]
505 fn test_csr_array() {
506 let rows = vec![0, 0, 1, 2, 2];
507 let cols = vec![0, 2, 2, 0, 1];
508 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
509 let shape = (3, 3);
510
511 let array =
512 CsrArray::from_triplets(&rows, &cols, &data, shape, false).expect("Operation failed");
513
514 assert_eq!(array.shape(), (3, 3));
515 assert_eq!(array.nnz(), 5);
516 assert!(is_sparse_array(&array));
517 }
518
519 #[test]
520 fn test_coo_array() {
521 let rows = vec![0, 0, 1, 2, 2];
522 let cols = vec![0, 2, 2, 0, 1];
523 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
524 let shape = (3, 3);
525
526 let array =
527 CooArray::from_triplets(&rows, &cols, &data, shape, false).expect("Operation failed");
528
529 assert_eq!(array.shape(), (3, 3));
530 assert_eq!(array.nnz(), 5);
531 assert!(is_sparse_array(&array));
532 }
533
534 #[test]
535 fn test_dok_array() {
536 let rows = vec![0, 0, 1, 2, 2];
537 let cols = vec![0, 2, 2, 0, 1];
538 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
539 let shape = (3, 3);
540
541 let array = DokArray::from_triplets(&rows, &cols, &data, shape).expect("Operation failed");
542
543 assert_eq!(array.shape(), (3, 3));
544 assert_eq!(array.nnz(), 5);
545 assert!(is_sparse_array(&array));
546
547 let mut array = DokArray::<f64>::new((2, 2));
549 array.set(0, 0, 1.0).expect("Operation failed");
550 array.set(1, 1, 2.0).expect("Operation failed");
551
552 assert_eq!(array.get(0, 0), 1.0);
553 assert_eq!(array.get(0, 1), 0.0);
554 assert_eq!(array.get(1, 1), 2.0);
555
556 array.set(0, 0, 0.0).expect("Operation failed");
558 assert_eq!(array.nnz(), 1);
559 }
560
561 #[test]
562 fn test_lil_array() {
563 let rows = vec![0, 0, 1, 2, 2];
564 let cols = vec![0, 2, 2, 0, 1];
565 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
566 let shape = (3, 3);
567
568 let array = LilArray::from_triplets(&rows, &cols, &data, shape).expect("Operation failed");
569
570 assert_eq!(array.shape(), (3, 3));
571 assert_eq!(array.nnz(), 5);
572 assert!(is_sparse_array(&array));
573
574 let mut array = LilArray::<f64>::new((2, 2));
576 array.set(0, 0, 1.0).expect("Operation failed");
577 array.set(1, 1, 2.0).expect("Operation failed");
578
579 assert_eq!(array.get(0, 0), 1.0);
580 assert_eq!(array.get(0, 1), 0.0);
581 assert_eq!(array.get(1, 1), 2.0);
582
583 assert!(array.has_sorted_indices());
585
586 array.set(0, 0, 0.0).expect("Operation failed");
588 assert_eq!(array.nnz(), 1);
589 }
590
591 #[test]
592 fn test_dia_array() {
593 use scirs2_core::ndarray::Array1;
594
595 let data = vec![
597 Array1::from_vec(vec![1.0, 2.0, 3.0]), Array1::from_vec(vec![4.0, 5.0, 0.0]), ];
600 let offsets = vec![0, 1]; let shape = (3, 3);
602
603 let array = DiaArray::new(data, offsets, shape).expect("Operation failed");
604
605 assert_eq!(array.shape(), (3, 3));
606 assert_eq!(array.nnz(), 5); assert!(is_sparse_array(&array));
608
609 assert_eq!(array.get(0, 0), 1.0);
611 assert_eq!(array.get(1, 1), 2.0);
612 assert_eq!(array.get(2, 2), 3.0);
613 assert_eq!(array.get(0, 1), 4.0);
614 assert_eq!(array.get(1, 2), 5.0);
615 assert_eq!(array.get(0, 2), 0.0);
616
617 let rows = vec![0, 0, 1, 1, 2];
619 let cols = vec![0, 1, 1, 2, 2];
620 let data_vec = vec![1.0, 4.0, 2.0, 5.0, 3.0];
621
622 let array2 =
623 DiaArray::from_triplets(&rows, &cols, &data_vec, shape).expect("Operation failed");
624
625 assert_eq!(array2.get(0, 0), 1.0);
627 assert_eq!(array2.get(1, 1), 2.0);
628 assert_eq!(array2.get(2, 2), 3.0);
629 assert_eq!(array2.get(0, 1), 4.0);
630 assert_eq!(array2.get(1, 2), 5.0);
631
632 let csr = array.to_csr().expect("Operation failed");
634 assert_eq!(csr.nnz(), 5);
635 assert_eq!(csr.get(0, 0), 1.0);
636 assert_eq!(csr.get(0, 1), 4.0);
637 }
638
639 #[test]
640 fn test_format_conversions() {
641 let rows = vec![0, 0, 1, 2, 2];
642 let cols = vec![0, 2, 1, 0, 2];
643 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
644 let shape = (3, 3);
645
646 let coo =
648 CooArray::from_triplets(&rows, &cols, &data, shape, false).expect("Operation failed");
649
650 let csr = coo.to_csr().expect("Operation failed");
652
653 let coo_dense = coo.to_array();
655 let csr_dense = csr.to_array();
656
657 for i in 0..shape.0 {
658 for j in 0..shape.1 {
659 assert_relative_eq!(coo_dense[[i, j]], csr_dense[[i, j]]);
660 }
661 }
662 }
663
664 #[test]
665 fn test_dot_product() {
666 let rows = vec![0, 0, 1, 2, 2];
667 let cols = vec![0, 2, 1, 0, 2];
668 let data = vec![1.0, 2.0, 3.0, 4.0, 5.0];
669 let shape = (3, 3);
670
671 let coo =
673 CooArray::from_triplets(&rows, &cols, &data, shape, false).expect("Operation failed");
674 let csr =
675 CsrArray::from_triplets(&rows, &cols, &data, shape, false).expect("Operation failed");
676
677 let coo_result = coo.dot(&coo).expect("Operation failed");
679 let csr_result = csr.dot(&csr).expect("Operation failed");
680
681 let coo_dense = coo_result.to_array();
683 let csr_dense = csr_result.to_array();
684
685 for i in 0..shape.0 {
686 for j in 0..shape.1 {
687 assert_relative_eq!(coo_dense[[i, j]], csr_dense[[i, j]], epsilon = 1e-10);
688 }
689 }
690 }
691
692 #[test]
693 fn test_sym_csr_array() {
694 let data = vec![2.0, 1.0, 2.0, 3.0, 0.0, 3.0, 1.0];
696 let indices = vec![0, 0, 1, 2, 0, 1, 2];
697 let indptr = vec![0, 1, 3, 7];
698
699 let sym_matrix =
700 SymCsrMatrix::new(data, indptr, indices, (3, 3)).expect("Operation failed");
701 let sym_array = SymCsrArray::new(sym_matrix);
702
703 assert_eq!(sym_array.shape(), (3, 3));
704 assert!(is_sym_sparse_array(&sym_array));
705
706 assert_eq!(SparseArray::get(&sym_array, 0, 0), 2.0);
708 assert_eq!(SparseArray::get(&sym_array, 0, 1), 1.0);
709 assert_eq!(SparseArray::get(&sym_array, 1, 0), 1.0); assert_eq!(SparseArray::get(&sym_array, 1, 2), 3.0);
711 assert_eq!(SparseArray::get(&sym_array, 2, 1), 3.0); let csr = SymSparseArray::to_csr(&sym_array).expect("Operation failed");
715 assert_eq!(csr.nnz(), 10); }
717
718 #[test]
719 fn test_sym_coo_array() {
720 let data = vec![2.0, 1.0, 2.0, 3.0, 1.0];
722 let rows = vec![0, 1, 1, 2, 2];
723 let cols = vec![0, 0, 1, 1, 2];
724
725 let sym_matrix = SymCooMatrix::new(data, rows, cols, (3, 3)).expect("Operation failed");
726 let sym_array = SymCooArray::new(sym_matrix);
727
728 assert_eq!(sym_array.shape(), (3, 3));
729 assert!(is_sym_sparse_array(&sym_array));
730
731 assert_eq!(SparseArray::get(&sym_array, 0, 0), 2.0);
733 assert_eq!(SparseArray::get(&sym_array, 0, 1), 1.0);
734 assert_eq!(SparseArray::get(&sym_array, 1, 0), 1.0); assert_eq!(SparseArray::get(&sym_array, 1, 2), 3.0);
736 assert_eq!(SparseArray::get(&sym_array, 2, 1), 3.0); let rows2 = vec![0, 0, 1, 1, 2, 1, 0];
741 let cols2 = vec![0, 1, 1, 2, 2, 0, 2];
742 let data2 = vec![2.0, 1.5, 2.0, 3.5, 1.0, 0.5, 0.0];
743
744 let sym_array2 = SymCooArray::from_triplets(&rows2, &cols2, &data2, (3, 3), true)
745 .expect("Operation failed");
746
747 assert_eq!(SparseArray::get(&sym_array2, 0, 1), 1.0); assert_eq!(SparseArray::get(&sym_array2, 1, 0), 1.0); assert_eq!(SparseArray::get(&sym_array2, 0, 2), 0.0); }
752
753 #[test]
754 fn test_construct_sym_utils() {
755 let eye = construct_sym::eye_sym_array::<f64>(3, "csr").expect("Operation failed");
757
758 assert_eq!(eye.shape(), (3, 3));
759 assert_eq!(SparseArray::get(&*eye, 0, 0), 1.0);
760 assert_eq!(SparseArray::get(&*eye, 1, 1), 1.0);
761 assert_eq!(SparseArray::get(&*eye, 2, 2), 1.0);
762 assert_eq!(SparseArray::get(&*eye, 0, 1), 0.0);
763
764 let diag = vec![2.0, 2.0, 2.0];
766 let offdiag = vec![1.0, 1.0];
767
768 let tri =
769 construct_sym::tridiagonal_sym_array(&diag, &offdiag, "coo").expect("Operation failed");
770
771 assert_eq!(tri.shape(), (3, 3));
772 assert_eq!(SparseArray::get(&*tri, 0, 0), 2.0); assert_eq!(SparseArray::get(&*tri, 1, 1), 2.0);
774 assert_eq!(SparseArray::get(&*tri, 2, 2), 2.0);
775 assert_eq!(SparseArray::get(&*tri, 0, 1), 1.0); assert_eq!(SparseArray::get(&*tri, 1, 0), 1.0); assert_eq!(SparseArray::get(&*tri, 1, 2), 1.0);
778 assert_eq!(SparseArray::get(&*tri, 0, 2), 0.0); let diagonals = vec![
782 vec![2.0, 2.0, 2.0, 2.0, 2.0], vec![1.0, 1.0, 1.0, 1.0], vec![0.5, 0.5, 0.5], ];
786
787 let band = construct_sym::banded_sym_array(&diagonals, 5, "csr").expect("Operation failed");
788
789 assert_eq!(band.shape(), (5, 5));
790 assert_eq!(SparseArray::get(&*band, 0, 0), 2.0);
791 assert_eq!(SparseArray::get(&*band, 0, 1), 1.0);
792 assert_eq!(SparseArray::get(&*band, 0, 2), 0.5);
793 assert_eq!(SparseArray::get(&*band, 2, 0), 0.5); }
795
796 #[test]
797 fn test_sym_conversions() {
798 let data = vec![2.0, 1.0, 2.0, 3.0, 1.0];
801 let rows = vec![0, 1, 1, 2, 2];
802 let cols = vec![0, 0, 1, 1, 2];
803
804 let sym_coo = SymCooArray::from_triplets(&rows, &cols, &data, (3, 3), true)
805 .expect("Operation failed");
806
807 let sym_csr = sym_coo.to_sym_csr().expect("Operation failed");
809
810 for i in 0..3 {
812 for j in 0..3 {
813 assert_eq!(
814 SparseArray::get(&sym_coo, i, j),
815 SparseArray::get(&sym_csr, i, j)
816 );
817 }
818 }
819
820 let csr = SymSparseArray::to_csr(&sym_coo).expect("Operation failed");
822 let coo = SymSparseArray::to_coo(&sym_csr).expect("Operation failed");
823
824 assert_eq!(csr.nnz(), 7); assert_eq!(coo.nnz(), 7);
827
828 for i in 0..3 {
829 for j in 0..3 {
830 assert_eq!(SparseArray::get(&csr, i, j), SparseArray::get(&coo, i, j));
831 assert_eq!(
832 SparseArray::get(&csr, i, j),
833 SparseArray::get(&sym_csr, i, j)
834 );
835 }
836 }
837 }
838}