#![warn(missing_docs)]
#![warn(clippy::all)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::multiple_bound_locations)]
pub mod builder;
pub mod auto;
pub mod fluent;
pub use oxiblas_blas as blas;
pub use oxiblas_core as core;
pub use oxiblas_lapack as lapack;
pub use oxiblas_matrix as matrix;
#[cfg(feature = "sparse")]
pub use oxiblas_sparse as sparse;
#[cfg(feature = "ndarray")]
pub use oxiblas_ndarray as ndarray;
pub use oxiblas_core::{
AlignedVec, Field, MemStack, Par, ParThreshold, Real, Scalar, SimdLevel, StackReq,
detect_simd_level, detect_simd_level_raw,
};
pub use oxiblas_core::{
ExtendedPrecision, HasFastFma, KBKSum, KahanSum, ScalarBatch, ScalarClass, ScalarClassify,
SimdCompatible, UnrollHints, pairwise_sum,
};
pub use oxiblas_core::{C32, C64, ComplexExt, I32, I64, ToComplex, c32, c64};
pub use oxiblas_matrix::{DiagRef, Mat, MatMut, MatRef, TransposeRef};
#[cfg(feature = "mmap")]
pub use oxiblas_matrix::{
MmapBuilder, MmapError, MmapMat, MmapMatMut, read_dimensions, write_mmap,
};
#[cfg(feature = "nalgebra")]
pub use oxiblas_matrix::{
DMatrixOxiblasExt, MatNalgebraExt, dmatrix_to_mat, dmatrix_view_to_mat, dvector_to_mat,
mat_ref_to_dmatrix, mat_to_dmatrix, mat_to_dvector,
};
pub use oxiblas_matrix::{
ComplexExpr, ComplexScalar, Expr, ExprAdd, ExprConj, ExprFma, ExprGemm, ExprHermitian,
ExprLeaf, ExprMul, ExprNeg, ExprScale, ExprSub, ExprTranspose, LazyExt,
};
pub use oxiblas_matrix::lazy::{fma as lazy_fma, gemm as lazy_gemm};
pub use oxiblas_blas::level3::{GemmBlocking, GemmKernel, gemm, gemm_with_par};
#[cfg(feature = "parallel")]
pub use oxiblas_core::{CustomRayonPool, RayonGlobalPool};
#[cfg(feature = "f16")]
pub use oxiblas_core::f16;
#[cfg(feature = "f128")]
pub use oxiblas_core::QuadFloat;
pub mod features {
pub const HAS_PARALLEL: bool = cfg!(feature = "parallel");
pub const HAS_SPARSE: bool = cfg!(feature = "sparse");
pub const HAS_F16: bool = cfg!(feature = "f16");
pub const HAS_F128: bool = cfg!(feature = "f128");
pub const HAS_NDARRAY: bool = cfg!(feature = "ndarray");
pub const NO_STD: bool = !cfg!(feature = "default");
}
pub mod prelude {
pub use crate::builder::MatBuilder;
pub use crate::fluent::{MatrixOps, MatrixOpsMut, VectorOps};
pub use oxiblas_core::prelude::*;
pub use oxiblas_core::{C32, C64, ComplexExt, I32, I64, ToComplex, c32, c64};
pub use oxiblas_core::{
ExtendedPrecision, KBKSum, KahanSum, ScalarBatch, SimdCompatible, pairwise_sum,
};
pub use oxiblas_matrix::prelude::*;
#[cfg(feature = "mmap")]
pub use oxiblas_matrix::{MmapBuilder, MmapMat, MmapMatMut};
#[cfg(feature = "f16")]
pub use oxiblas_core::f16;
#[cfg(feature = "f128")]
pub use oxiblas_core::QuadFloat;
#[cfg(feature = "parallel")]
pub use oxiblas_core::{CustomRayonPool, RayonGlobalPool};
pub use crate::{lazy_fma, lazy_gemm};
pub use oxiblas_blas::prelude::*;
#[cfg(feature = "sparse")]
pub use oxiblas_sparse::{CooMatrix, CscMatrix, CsrMatrix};
#[cfg(feature = "sparse")]
pub use oxiblas_sparse::linalg::{bicgstab, cg, gmres};
#[allow(unused_imports)]
pub use oxiblas_lapack::prelude::{
BandCholesky, BandCholeskyError, BandLu, BandLuError, BidiagError, BidiagFactors,
BidiagVect, Cholesky, CholeskyError, CholeskyInfo, CondError, DetError, Eigenvalue,
EigenvalueSelector, Equilibrate, ErrorCategory, ErrorCode, EvdInfo, EvdWorkspaceQuery,
ExpertCholeskySolveError, ExpertCholeskySolveResult, ExpertSolveError, ExpertSolveResult,
ExpertSymmetricSolveError, ExpertSymmetricSolveResult, GeneralEvd, GeneralEvdError,
HasInfoCode, Hessenberg, HessenbergError, INFO_SUCCESS, InfoCode, IntoLapackError,
InvError, LapackError, LapackResult, Ldlt, LdltError, LeastSquaresResult, LstSqError, Lu,
LuError, LuFullPiv, LuFullPivError, LuInfo, PinvResult, Qr, QrError, QrInfo, QrPivot,
QrPivotError, RandomizedSvd, RandomizedSvdConfig, RandomizedSvdError, RankError,
RefinementError, RefinementResult, Schur, SchurError, SelectiveSvd, SelectiveSvdError,
SingularValueSelector, SolveError, Svd, SvdDc, SvdDcError, SvdError, SvdInfo,
SvdWorkspaceQuery, SymmetricEvd, SymmetricEvdDc, SymmetricEvdDcError, SymmetricEvdError,
SymmetricEvdInfo, TriangularKind, TriangularSolveError, TridiagError, TridiagEvd,
TridiagEvdError, TridiagFactors, TridiagSPDFactors, Workspace, WorkspaceQuery,
WorkspaceQueryWithInt, band_lower_to_dense, band_lu_workspace, band_to_dense,
bidiag_workspace, cholesky_solve_workspace, cholesky_workspace, col_space,
compute_cholesky_info, compute_general_evd_info, compute_lu_info, compute_qr_info,
compute_svd_info, compute_symmetric_evd_info, cond, cond_1, cond_inf, count_eigenvalues,
count_singular_values_above, dense_to_band, dense_to_band_lower, det, det_lu,
eigenvalue_bounds, eigenvalues_by_index, eigenvalues_in_range, gebrd,
general_evd_workspace, generalized_evd_workspace, hermitian_evd_workspace,
hessenberg_workspace, inv, ldlt_workspace, least_squares_workspace, left_null_space,
low_rank_approximation, lstsq, lu_solve_workspace, lu_workspace, norm_1, norm_2,
norm_frobenius, norm_inf, norm_max, norm_nuclear, null_space, nullity, orgbr,
orgqr_workspace, ormbr, ormqr_workspace, pinv, pinv_default, qr_pivot_workspace,
qr_workspace, qz_workspace, rank, rcond, rcond_estimate, refine_solution,
refine_solution_cholesky, refine_solution_symmetric, row_space, rsvd, rsvd_power,
schur_workspace, singular_value_bounds, solve, solve_cholesky_expert, solve_expert,
solve_multiple, solve_symmetric_expert, solve_triangular, solve_triangular_multiple,
svd_dc_workspace, svd_workspace, symmetric_evd_dc_workspace, symmetric_evd_workspace,
trace, triangular_solve_workspace, tridiag_factor, tridiag_factor_spd, tridiag_solve,
tridiag_solve_factored, tridiag_solve_factored_spd, tridiag_solve_multiple,
tridiag_solve_spd, tridiagonal_solve_workspace, ungbr, unmbr,
};
}
#[cfg(test)]
mod tests {
use super::prelude::*;
#[test]
fn test_basic_workflow() {
let a: Mat<f64> = Mat::from_rows(&[&[1.0, 2.0], &[3.0, 4.0]]);
let b: Mat<f64> = Mat::from_rows(&[&[5.0, 6.0], &[7.0, 8.0]]);
let mut c: Mat<f64> = Mat::zeros(2, 2);
gemm(1.0, a.as_ref(), b.as_ref(), 0.0, c.as_mut());
assert!((c[(0, 0)] - 19.0).abs() < 1e-10);
assert!((c[(0, 1)] - 22.0).abs() < 1e-10);
assert!((c[(1, 0)] - 43.0).abs() < 1e-10);
assert!((c[(1, 1)] - 50.0).abs() < 1e-10);
}
#[test]
fn test_simd_detection() {
let level = detect_simd_level();
println!("Detected SIMD level: {:?}", level);
assert!(level >= SimdLevel::Scalar);
}
#[test]
fn test_aligned_allocation() {
let vec: AlignedVec<f64> = AlignedVec::zeros(100);
let ptr = vec.as_ptr();
assert_eq!(ptr as usize % 64, 0);
}
#[test]
fn test_scalar_batch_operations() {
use super::ScalarBatch;
let x = [1.0f64, 2.0, 3.0, 4.0];
let y = [5.0f64, 6.0, 7.0, 8.0];
let dot = f64::dot_batch(&x, &y);
assert!((dot - 70.0).abs() < 1e-10); }
#[test]
fn test_complex_ergonomics() {
use super::{ComplexExt, I64, c64};
let z = c64(3.0, 4.0);
assert_eq!(z.re, 3.0);
assert_eq!(z.im, 4.0);
let i = I64;
assert_eq!(i.re, 0.0);
assert_eq!(i.im, 1.0);
let normalized = z.normalize();
let mag = (normalized.re * normalized.re + normalized.im * normalized.im).sqrt();
assert!((mag - 1.0).abs() < 1e-10);
}
#[test]
fn test_compensated_sum() {
use super::{KahanSum, pairwise_sum};
let mut kahan = KahanSum::<f64>::new();
for _ in 0..1000 {
kahan.add(0.1);
}
assert!((kahan.sum() - 100.0).abs() < 1e-10);
let values: Vec<f64> = (0..1000).map(|_| 0.1).collect();
let result = pairwise_sum(&values);
assert!((result - 100.0).abs() < 1e-10);
}
#[test]
fn test_lazy_evaluation() {
use super::{Expr, LazyExt};
let a: Mat<f64> = Mat::from_rows(&[&[1.0, 2.0], &[3.0, 4.0]]);
let b: Mat<f64> = Mat::from_rows(&[&[5.0, 6.0], &[7.0, 8.0]]);
let expr = a.as_ref().lazy() + b.as_ref().lazy();
let result = expr.eval();
assert!((result[(0, 0)] - 6.0).abs() < 1e-10); assert!((result[(0, 1)] - 8.0).abs() < 1e-10); assert!((result[(1, 0)] - 10.0).abs() < 1e-10); assert!((result[(1, 1)] - 12.0).abs() < 1e-10);
let scaled_expr = (a.as_ref().lazy() + b.as_ref().lazy()).scale(2.0);
let result2 = scaled_expr.eval();
assert!((result2[(0, 0)] - 12.0).abs() < 1e-10); assert!((result2[(1, 1)] - 24.0).abs() < 1e-10); }
#[test]
fn test_lazy_fma_gemm() {
use super::{Expr, LazyExt, lazy_fma, lazy_gemm};
let a: Mat<f64> = Mat::from_rows(&[&[1.0, 2.0], &[3.0, 4.0]]);
let b: Mat<f64> = Mat::from_rows(&[&[5.0, 6.0], &[7.0, 8.0]]);
let fma_expr = lazy_fma(2.0, a.as_ref().lazy(), 3.0, b.as_ref().lazy());
let result = fma_expr.eval();
assert!((result[(0, 0)] - 17.0).abs() < 1e-10); assert!((result[(1, 1)] - 32.0).abs() < 1e-10);
let identity: Mat<f64> = Mat::eye(2);
let gemm_expr = lazy_gemm(
1.0,
a.as_ref().lazy(),
identity.as_ref().lazy(),
0.0,
a.as_ref().lazy(),
);
let result2 = gemm_expr.eval();
assert!((result2[(0, 0)] - 1.0).abs() < 1e-10);
assert!((result2[(1, 1)] - 4.0).abs() < 1e-10);
}
}