1#![cfg_attr(not(feature = "std"), no_std)]
161#![allow(non_snake_case)]
162#![warn(missing_docs)]
163#![warn(rustdoc::broken_intra_doc_links)]
164
165extern crate alloc;
166#[cfg(feature = "std")]
167extern crate std;
168
169#[macro_export]
171macro_rules! make_guard {
172 ($($name:ident),* $(,)?) => {$(
173 #[allow(unused_unsafe)]
174 let $name = unsafe { extern crate generativity; ::generativity::Id::new() };
175 #[allow(unused, unused_unsafe)]
176 let lifetime_brand = unsafe { extern crate generativity; ::generativity::LifetimeBrand::new(&$name) };
177 #[allow(unused_unsafe)]
178 let $name = unsafe { extern crate generativity; ::generativity::Guard::new($name) };
179 )*};
180}
181
182macro_rules! repeat_n {
183 ($e: expr, $n: expr) => {
184 iter::repeat_n($e, $n)
185 };
186}
187
188macro_rules! try_const {
189 ($e: expr) => {
190 ::pulp::try_const! { $e }
191 };
192}
193
194use core::num::NonZeroUsize;
195use core::sync::atomic::AtomicUsize;
196use equator::{assert, debug_assert};
197use faer_traits::*;
198
199macro_rules! auto {
200 ($ty: ty) => {
201 $crate::Auto::<$ty>::auto()
202 };
203}
204
205macro_rules! dispatch {
206 ($imp: expr, $ty: ident, $T: ty $(,)?) => {
207 if try_const! { <$T>::IS_NATIVE_C32 } {
208 unsafe { transmute(<ComplexImpl<f32> as ComplexField>::Arch::default().dispatch(transmute::<_, $ty<ComplexImpl<f32>>>($imp))) }
209 } else if try_const! { <$T>::IS_NATIVE_C64 } {
210 unsafe { transmute(<ComplexImpl<f64> as ComplexField>::Arch::default().dispatch(transmute::<_, $ty<ComplexImpl<f64>>>($imp))) }
211 } else {
212 <$T>::Arch::default().dispatch($imp)
213 }
214 };
215}
216
217macro_rules! stack_mat {
218 ($name: ident, $m: expr, $n: expr, $A: expr, $N: expr, $T: ty $(,)?) => {
219 let mut __tmp = {
220 #[repr(align(64))]
221 struct __Col<T, const A: usize>([T; A]);
222 struct __Mat<T, const A: usize, const N: usize>([__Col<T, A>; N]);
223
224 core::mem::MaybeUninit::<__Mat<$T, $A, $N>>::uninit()
225 };
226 let __stack = MemStack::new_any(core::slice::from_mut(&mut __tmp));
227 let mut $name = $crate::linalg::temp_mat_zeroed::<$T, _, _>($m, $n, __stack).0;
228 let mut $name = $name.as_mat_mut();
229 };
230
231 ($name: ident, $m: expr, $n: expr, $T: ty $(,)?) => {
232 stack_mat!($name, $m, $n, $m, $n, $T)
233 };
234}
235
236#[macro_export]
237#[doc(hidden)]
238macro_rules! __dbg {
239 () => {
240 std::eprintln!("[{}:{}:{}]", std::file!(), std::line!(), std::column!())
241 };
242 ($val:expr $(,)?) => {
243 match $val {
244 tmp => {
245 std::eprintln!("[{}:{}:{}] {} = {:16.12?}",
246 std::file!(), std::line!(), std::column!(), std::stringify!($val), &tmp);
247 tmp
248 }
249 }
250 };
251 ($($val:expr),+ $(,)?) => {
252 ($($crate::__dbg!($val)),+,)
253 };
254}
255
256#[cfg(feature = "perf-warn")]
257#[macro_export]
258#[doc(hidden)]
259macro_rules! __perf_warn {
260 ($name: ident) => {{
261 #[inline(always)]
262 #[allow(non_snake_case)]
263 fn $name() -> &'static ::core::sync::atomic::AtomicBool {
264 static $name: ::core::sync::atomic::AtomicBool = ::core::sync::atomic::AtomicBool::new(false);
265 &$name
266 }
267 ::core::matches!(
268 $name().compare_exchange(
269 false,
270 true,
271 ::core::sync::atomic::Ordering::Relaxed,
272 ::core::sync::atomic::Ordering::Relaxed,
273 ),
274 Ok(_)
275 )
276 }};
277}
278
279#[doc(hidden)]
280#[macro_export]
281macro_rules! with_dim {
282 ($name: ident, $value: expr $(,)?) => {
283 let __val__ = $value;
284 $crate::make_guard!($name);
285 let $name = $crate::utils::bound::Dim::new(__val__, $name);
286 };
287
288 ({$(let $name: ident = $value: expr;)*}) => {$(
289 let __val__ = $value;
290 $crate::make_guard!($name);
291 let $name = $crate::utils::bound::Dim::new(__val__, $name);
292 )*};
293}
294
295#[macro_export]
323macro_rules! zip {
324 ($head: expr $(,)?) => {
325 $crate::linalg::zip::LastEq($crate::linalg::zip::IntoView::into_view($head), ::core::marker::PhantomData)
326 };
327
328 ($head: expr, $($tail: expr),* $(,)?) => {
329 $crate::linalg::zip::ZipEq::new($crate::linalg::zip::IntoView::into_view($head), $crate::zip!($($tail,)*))
330 };
331}
332
333#[macro_export]
357macro_rules! unzip {
358 ($head: pat $(,)?) => {
359 $crate::linalg::zip::Last($head)
360 };
361
362 ($head: pat, $($tail: pat),* $(,)?) => {
363 $crate::linalg::zip::Zip($head, $crate::unzip!($($tail,)*))
364 };
365}
366
367#[macro_export]
368#[doc(hidden)]
369macro_rules! __transpose_impl {
370 ([$([$($col:expr),*])*] $($v:expr;)* ) => {
371 [$([$($col,)*],)* [$($v,)*]]
372 };
373 ([$([$($col:expr),*])*] $($v0:expr, $($v:expr),* ;)*) => {
374 $crate::__transpose_impl!([$([$($col),*])* [$($v0),*]] $($($v),* ;)*)
375 };
376}
377
378#[macro_export]
406macro_rules! mat {
407 () => {
408 {
409 compile_error!("number of columns in the matrix is ambiguous");
410 }
411 };
412
413 ($([$($v:expr),* $(,)?] ),* $(,)?) => {
414 {
415 let __data = ::core::mem::ManuallyDrop::new($crate::__transpose_impl!([] $($($v),* ;)*));
416 let __data = &*__data;
417 let __ncols = __data.len();
418 let __nrows = (*__data.get(0).unwrap()).len();
419
420 #[allow(unused_unsafe)]
421 unsafe {
422 $crate::mat::Mat::from_fn(__nrows, __ncols, |i, j| ::core::ptr::from_ref(&__data[j][i]).read())
423 }
424 }
425 };
426}
427
428#[macro_export]
441macro_rules! col {
442 ($($v: expr),* $(,)?) => {
443 {
444 let __data = ::core::mem::ManuallyDrop::new([$($v,)*]);
445 let __data = &*__data;
446 let __len = __data.len();
447
448 #[allow(unused_unsafe)]
449 unsafe {
450 $crate::col::Col::from_fn(__len, |i| ::core::ptr::from_ref(&__data[i]).read())
451 }
452 }
453 };
454}
455
456#[macro_export]
469macro_rules! row {
470 ($($v: expr),* $(,)?) => {
471 {
472 let __data = ::core::mem::ManuallyDrop::new([$($v,)*]);
473 let __data = &*__data;
474 let __len = __data.len();
475
476 #[allow(unused_unsafe)]
477 unsafe {
478 $crate::row::Row::from_fn(__len, |i| ::core::ptr::from_ref(&__data[i]).read())
479 }
480 }
481 };
482}
483
484#[doc(hidden)]
495#[track_caller]
496pub fn concat_impl<T: ComplexField>(blocks: &[&[(mat::MatRef<'_, T>, Conj)]]) -> mat::Mat<T> {
497 #[inline(always)]
498 fn count_total_columns<T: ComplexField>(block_row: &[(mat::MatRef<'_, T>, Conj)]) -> usize {
499 let mut out: usize = 0;
500 for (elem, _) in block_row.iter() {
501 out += elem.ncols();
502 }
503 out
504 }
505
506 #[inline(always)]
507 #[track_caller]
508 fn count_rows<T: ComplexField>(block_row: &[(mat::MatRef<'_, T>, Conj)]) -> usize {
509 let mut out: usize = 0;
510 for (i, (e, _)) in block_row.iter().enumerate() {
511 if i == 0 {
512 out = e.nrows();
513 } else {
514 assert!(e.nrows() == out);
515 }
516 }
517 out
518 }
519
520 let mut n: usize = 0;
522 let mut m: usize = 0;
523 for row in blocks.iter() {
524 n += count_rows(row);
525 }
526 for (i, row) in blocks.iter().enumerate() {
527 let cols = count_total_columns(row);
528 if i == 0 {
529 m = cols;
530 } else {
531 assert!(cols == m);
532 }
533 }
534
535 let mut mat = mat::Mat::<T>::zeros(n, m);
536 let mut ni: usize = 0;
537 let mut mj: usize;
538 for row in blocks.iter() {
539 mj = 0;
540
541 for (elem, conj) in row.iter() {
542 let mut dst = mat.as_mut().submatrix_mut(ni, mj, elem.nrows(), elem.ncols());
543 if *conj == Conj::No {
544 dst.copy_from(elem);
545 } else {
546 dst.copy_from(elem.conjugate());
547 }
548 mj += elem.ncols();
549 }
550 ni += row[0].0.nrows();
551 }
552
553 mat
554}
555
556#[macro_export]
564macro_rules! concat {
565 () => {
566 {
567 compile_error!("number of columns in the matrix is ambiguous");
568 }
569 };
570
571 ($([$($v:expr),* $(,)?] ),* $(,)?) => {
572 {
573 $crate::concat_impl(&[$(&[$(($v).as_ref().__canonicalize(),)*],)*])
574 }
575 };
576}
577
578pub mod utils;
580
581pub mod diag;
583pub mod mat;
585pub mod perm;
587
588pub mod col;
590pub mod row;
592
593pub mod linalg;
594#[path = "./operator/mod.rs"]
595pub mod matrix_free;
596pub mod sparse;
597
598#[cfg(feature = "std")]
600pub mod io;
601
602#[cfg(feature = "serde")]
603mod serde;
604
605pub trait Index: traits::IndexCore + traits::Index + seal::Seal {}
607impl<T: faer_traits::Index<Signed: seal::Seal> + seal::Seal> Index for T {}
608
609mod seal {
610 pub trait Seal {}
611 impl<T: faer_traits::Seal> Seal for T {}
612 impl Seal for crate::utils::bound::Dim<'_> {}
613 impl<I: crate::Index> Seal for crate::utils::bound::Idx<'_, I> {}
614 impl<I: crate::Index> Seal for crate::utils::bound::IdxInc<'_, I> {}
615 impl<I: crate::Index> Seal for crate::utils::bound::MaybeIdx<'_, I> {}
616 impl<I: crate::Index> Seal for crate::utils::bound::IdxIncOne<I> {}
617 impl<I: crate::Index> Seal for crate::utils::bound::MaybeIdxOne<I> {}
618 impl Seal for crate::utils::bound::One {}
619 impl Seal for crate::utils::bound::Zero {}
620 impl Seal for crate::ContiguousFwd {}
621 impl Seal for crate::ContiguousBwd {}
622}
623
624pub trait Unbind<I = usize>: Send + Sync + Copy + core::fmt::Debug + seal::Seal {
627 unsafe fn new_unbound(idx: I) -> Self;
631
632 fn unbound(self) -> I;
634}
635
636pub type Idx<Dim, I = usize> = <Dim as ShapeIdx>::Idx<I>;
638pub type IdxInc<Dim, I = usize> = <Dim as ShapeIdx>::IdxInc<I>;
640pub type MaybeIdx<Dim, I = usize> = <Dim as ShapeIdx>::MaybeIdx<I>;
642
643pub trait ShapeIdx {
645 type Idx<I: Index>: Unbind<I> + Ord + Eq;
647 type IdxInc<I: Index>: Unbind<I> + Ord + Eq + From<Idx<Self, I>>;
649 type MaybeIdx<I: Index>: Unbind<I::Signed> + Ord + Eq;
651}
652
653pub trait Shape: Unbind + Ord + ShapeIdx<Idx<usize>: Ord + Eq + PartialOrd<Self>, IdxInc<usize>: Ord + Eq + PartialOrd<Self>> {
655 const IS_BOUND: bool = true;
657
658 #[inline]
660 fn bind<'n>(self, guard: generativity::Guard<'n>) -> utils::bound::Dim<'n> {
661 utils::bound::Dim::new(self.unbound(), guard)
662 }
663
664 #[inline]
666 fn cast_idx_slice<I: Index>(slice: &[Idx<Self, I>]) -> &[I] {
667 unsafe { core::slice::from_raw_parts(slice.as_ptr() as _, slice.len()) }
668 }
669
670 #[inline]
672 fn cast_idx_inc_slice<I: Index>(slice: &[IdxInc<Self, I>]) -> &[I] {
673 unsafe { core::slice::from_raw_parts(slice.as_ptr() as _, slice.len()) }
674 }
675
676 #[inline(always)]
678 fn start() -> IdxInc<Self> {
679 unsafe { IdxInc::<Self>::new_unbound(0) }
680 }
681
682 #[inline(always)]
684 fn next(idx: Idx<Self>) -> IdxInc<Self> {
685 unsafe { IdxInc::<Self>::new_unbound(idx.unbound() + 1) }
686 }
687
688 #[inline(always)]
690 fn end(self) -> IdxInc<Self> {
691 unsafe { IdxInc::<Self>::new_unbound(self.unbound()) }
692 }
693
694 #[inline(always)]
696 fn idx(self, idx: usize) -> Option<Idx<Self>> {
697 if idx < self.unbound() {
698 Some(unsafe { Idx::<Self>::new_unbound(idx) })
699 } else {
700 None
701 }
702 }
703
704 #[inline(always)]
706 fn idx_inc(self, idx: usize) -> Option<IdxInc<Self>> {
707 if idx <= self.unbound() {
708 Some(unsafe { IdxInc::<Self>::new_unbound(idx) })
709 } else {
710 None
711 }
712 }
713
714 #[inline(always)]
716 fn checked_idx(self, idx: usize) -> Idx<Self> {
717 equator::assert!(idx < self.unbound());
718 unsafe { Idx::<Self>::new_unbound(idx) }
719 }
720
721 #[inline(always)]
723 fn checked_idx_inc(self, idx: usize) -> IdxInc<Self> {
724 equator::assert!(idx <= self.unbound());
725 unsafe { IdxInc::<Self>::new_unbound(idx) }
726 }
727
728 #[inline(always)]
732 unsafe fn unchecked_idx(self, idx: usize) -> Idx<Self> {
733 equator::debug_assert!(idx < self.unbound());
734 unsafe { Idx::<Self>::new_unbound(idx) }
735 }
736
737 #[inline(always)]
741 unsafe fn unchecked_idx_inc(self, idx: usize) -> IdxInc<Self> {
742 equator::debug_assert!(idx <= self.unbound());
743 unsafe { IdxInc::<Self>::new_unbound(idx) }
744 }
745
746 #[inline(always)]
748 fn indices(from: IdxInc<Self>, to: IdxInc<Self>) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<Self>> {
749 (from.unbound()..to.unbound()).map(
750 #[inline(always)]
751 |i| unsafe { Idx::<Self>::new_unbound(i) },
752 )
753 }
754}
755
756impl<T: Send + Sync + Copy + core::fmt::Debug + faer_traits::Seal> Unbind<T> for T {
757 #[inline(always)]
758 unsafe fn new_unbound(idx: T) -> Self {
759 idx
760 }
761
762 #[inline(always)]
763 fn unbound(self) -> T {
764 self
765 }
766}
767
768impl ShapeIdx for usize {
769 type Idx<I: Index> = I;
770 type IdxInc<I: Index> = I;
771 type MaybeIdx<I: Index> = I::Signed;
772}
773impl Shape for usize {
774 const IS_BOUND: bool = false;
775}
776
777pub trait Stride: seal::Seal + core::fmt::Debug + Copy + Send + Sync + 'static {
779 type Rev: Stride<Rev = Self>;
781 fn rev(self) -> Self::Rev;
783
784 fn element_stride(self) -> isize;
786}
787
788impl Stride for isize {
789 type Rev = Self;
790
791 #[inline(always)]
792 fn rev(self) -> Self::Rev {
793 -self
794 }
795
796 #[inline(always)]
797 fn element_stride(self) -> isize {
798 self
799 }
800}
801
802#[derive(Copy, Clone, Debug)]
804pub struct ContiguousFwd;
805#[derive(Copy, Clone, Debug)]
807pub struct ContiguousBwd;
808
809impl Stride for ContiguousFwd {
810 type Rev = ContiguousBwd;
811
812 #[inline(always)]
813 fn rev(self) -> Self::Rev {
814 ContiguousBwd
815 }
816
817 #[inline(always)]
818 fn element_stride(self) -> isize {
819 1
820 }
821}
822
823impl Stride for ContiguousBwd {
824 type Rev = ContiguousFwd;
825
826 #[inline(always)]
827 fn rev(self) -> Self::Rev {
828 ContiguousFwd
829 }
830
831 #[inline(always)]
832 fn element_stride(self) -> isize {
833 -1
834 }
835}
836
837#[derive(Copy, Clone, Debug, PartialEq, Eq)]
839pub enum TryReserveError {
840 CapacityOverflow,
842 AllocError {
844 layout: core::alloc::Layout,
846 },
847}
848
849#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
851pub enum Conj {
852 No,
854 Yes,
856}
857
858#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
859pub(crate) enum DiagStatus {
860 Unit,
861 Generic,
862}
863
864#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
866pub enum Accum {
867 Replace,
869 Add,
871}
872
873#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
875pub enum Side {
876 Lower,
878 Upper,
880}
881
882impl Conj {
883 #[inline]
885 pub const fn is_conj(self) -> bool {
886 matches!(self, Conj::Yes)
887 }
888
889 #[inline]
891 pub const fn compose(self, other: Self) -> Self {
892 match (self, other) {
893 (Conj::No, Conj::No) => Conj::No,
894 (Conj::Yes, Conj::Yes) => Conj::No,
895 (Conj::No, Conj::Yes) => Conj::Yes,
896 (Conj::Yes, Conj::No) => Conj::Yes,
897 }
898 }
899
900 #[inline]
902 pub const fn get<T: Conjugate>() -> Self {
903 if T::IS_CANONICAL { Self::No } else { Self::Yes }
904 }
905
906 #[inline]
907 pub(crate) fn apply<T: Conjugate>(value: &T) -> T::Canonical {
908 let value = unsafe { &*(value as *const T as *const T::Canonical) };
909
910 if try_const! { matches!(Self::get::<T>(), Conj::Yes) } {
911 T::Canonical::conj_impl(value)
912 } else {
913 T::Canonical::copy_impl(value)
914 }
915 }
916
917 #[inline]
918 pub(crate) fn apply_rt<T: ComplexField>(self, value: &T) -> T {
919 if self.is_conj() { T::conj_impl(value) } else { T::copy_impl(value) }
920 }
921}
922
923#[derive(Copy, Clone, Debug, PartialEq, Eq)]
925pub enum Par {
926 Seq,
928 #[cfg(feature = "rayon")]
930 Rayon(NonZeroUsize),
931}
932
933impl Par {
934 #[inline]
937 #[cfg(feature = "rayon")]
938 pub fn rayon(nthreads: usize) -> Self {
939 if nthreads == 0 {
940 Self::Rayon(NonZeroUsize::new(rayon::current_num_threads()).unwrap())
941 } else {
942 Self::Rayon(NonZeroUsize::new(nthreads).unwrap())
943 }
944 }
945
946 #[inline]
948 pub fn degree(&self) -> usize {
949 utils::thread::parallelism_degree(*self)
950 }
951}
952
953#[allow(non_camel_case_types)]
954pub type c32 = traits::c32;
956#[allow(non_camel_case_types)]
957pub type c64 = traits::c64;
959#[allow(non_camel_case_types)]
960pub type cx128 = traits::cx128;
962#[allow(non_camel_case_types)]
963pub type fx128 = traits::fx128;
965
966pub use col::{Col, ColMut, ColRef};
967pub use mat::{Mat, MatMut, MatRef};
968pub use row::{Row, RowMut, RowRef};
969
970#[allow(unused_imports, dead_code)]
971mod internal_prelude {
972 pub trait DivCeil: Sized {
973 fn msrv_div_ceil(self, rhs: Self) -> Self;
974 fn msrv_next_multiple_of(self, rhs: Self) -> Self;
975 fn msrv_checked_next_multiple_of(self, rhs: Self) -> Option<Self>;
976 }
977
978 impl DivCeil for usize {
979 #[inline]
980 fn msrv_div_ceil(self, rhs: Self) -> Self {
981 let d = self / rhs;
982 let r = self % rhs;
983 if r > 0 { d + 1 } else { d }
984 }
985
986 #[inline]
987 fn msrv_next_multiple_of(self, rhs: Self) -> Self {
988 match self % rhs {
989 0 => self,
990 r => self + (rhs - r),
991 }
992 }
993
994 #[inline]
995 fn msrv_checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
996 {
997 match self.checked_rem(rhs)? {
998 0 => Some(self),
999 r => self.checked_add(rhs - r),
1000 }
1001 }
1002 }
1003 }
1004
1005 #[cfg(test)]
1006 pub(crate) use std::dbg;
1007 #[cfg(test)]
1008 pub(crate) use {alloc::boxed::Box, alloc::vec, alloc::vec::Vec};
1009
1010 pub use faer_traits::{ComplexImpl, ComplexImplConj, Symbolic};
1011
1012 pub(crate) use crate::col::{Col, ColMut, ColRef};
1013 pub(crate) use crate::diag::{Diag, DiagMut, DiagRef};
1014 pub(crate) use crate::hacks::transmute;
1015 pub(crate) use crate::linalg::{self, temp_mat_scratch, temp_mat_uninit, temp_mat_zeroed};
1016 pub(crate) use crate::mat::{AsMat, AsMatMut, AsMatRef, Mat, MatMut, MatRef};
1017 pub(crate) use crate::perm::{Perm, PermRef};
1018 pub(crate) use crate::prelude::*;
1019 pub(crate) use crate::row::{AsRowMut, AsRowRef, Row, RowMut, RowRef};
1020 pub(crate) use crate::utils::bound::{Array, Dim, Idx, IdxInc, MaybeIdx};
1021 pub(crate) use crate::utils::simd::SimdCtx;
1022 pub(crate) use crate::{Auto, NonExhaustive, Side, Spec};
1023
1024 pub use num_complex::Complex;
1025
1026 pub use faer_macros::math;
1027 pub use faer_traits::math_utils::*;
1028 pub use faer_traits::{ComplexField, Conjugate, Index, IndexCore, Real, RealField, SignedIndex, SimdArch};
1029
1030 #[inline]
1031 pub fn simd_align(i: usize) -> usize {
1032 i.wrapping_neg()
1033 }
1034
1035 pub(crate) use crate::{Accum, Conj, ContiguousBwd, ContiguousFwd, DiagStatus, Par, Shape, Stride, Unbind, unzip, zip};
1036
1037 pub use {unzip as uz, zip as z};
1038
1039 pub use crate::make_guard;
1040 pub use dyn_stack::{MemStack, StackReq};
1041 pub use equator::{assert, assert as Assert, debug_assert, debug_assert as DebugAssert};
1042 pub use reborrow::*;
1043}
1044
1045#[allow(unused_imports)]
1046pub(crate) mod internal_prelude_sp {
1047 pub(crate) use crate::internal_prelude::*;
1048 pub(crate) use crate::sparse::{
1049 FaerError, NONE, Pair, SparseColMat, SparseColMatMut, SparseColMatRef, SparseRowMat, SparseRowMatMut, SparseRowMatRef, SymbolicSparseColMat,
1050 SymbolicSparseColMatRef, SymbolicSparseRowMat, SymbolicSparseRowMatRef, Triplet, csc_numeric, csc_symbolic, csr_numeric, csr_symbolic,
1051 linalg as linalg_sp, try_collect, try_zeroed, windows2,
1052 };
1053 pub(crate) use core::cell::Cell;
1054 pub(crate) use core::iter;
1055 pub(crate) use dyn_stack::MemBuffer;
1056}
1057
1058pub mod prelude {
1060 pub use reborrow::{IntoConst, Reborrow, ReborrowMut};
1061
1062 pub use super::{Par, Scale, c32, c64, col, mat, row, unzip, zip};
1063 pub use col::{Col, ColMut, ColRef};
1064 pub use mat::{Mat, MatMut, MatRef};
1065 pub use row::{Row, RowMut, RowRef};
1066
1067 #[cfg(feature = "linalg")]
1068 pub use super::linalg::solvers::{DenseSolve, Solve, SolveLstsq};
1069
1070 #[cfg(feature = "sparse")]
1071 pub use super::prelude_sp::*;
1072
1073 #[inline]
1075 pub fn default<T: Default>() -> T {
1076 Default::default()
1077 }
1078}
1079
1080#[cfg(feature = "sparse")]
1081mod prelude_sp {
1082 use crate::sparse;
1083
1084 pub use sparse::{SparseColMat, SparseColMatMut, SparseColMatRef, SparseRowMat, SparseRowMatMut, SparseRowMatRef};
1085}
1086
1087#[derive(Copy, Clone, Debug)]
1089#[repr(transparent)]
1090pub struct Scale<T>(pub T);
1091impl<T> Scale<T> {
1092 #[inline(always)]
1094 pub fn from_ref(value: &T) -> &Self {
1095 unsafe { &*(value as *const T as *const Self) }
1096 }
1097
1098 #[inline(always)]
1100 pub fn from_mut(value: &mut T) -> &mut Self {
1101 unsafe { &mut *(value as *mut T as *mut Self) }
1102 }
1103}
1104
1105static GLOBAL_PARALLELISM: AtomicUsize = {
1111 #[cfg(all(not(miri), feature = "rayon"))]
1112 {
1113 AtomicUsize::new(2)
1114 }
1115 #[cfg(not(all(not(miri), feature = "rayon")))]
1116 {
1117 AtomicUsize::new(1)
1118 }
1119};
1120
1121pub fn disable_global_parallelism() {
1123 GLOBAL_PARALLELISM.store(0, core::sync::atomic::Ordering::Relaxed);
1124}
1125
1126pub fn set_global_parallelism(par: Par) {
1128 let value = match par {
1129 Par::Seq => 1,
1130 #[cfg(feature = "rayon")]
1131 Par::Rayon(n) => n.get().saturating_add(2),
1132 };
1133 GLOBAL_PARALLELISM.store(value, core::sync::atomic::Ordering::Relaxed);
1134}
1135
1136#[track_caller]
1141pub fn get_global_parallelism() -> Par {
1142 let value = GLOBAL_PARALLELISM.load(core::sync::atomic::Ordering::Relaxed);
1143 match value {
1144 0 => panic!("Global parallelism is disabled."),
1145 1 => Par::Seq,
1146 #[cfg(feature = "rayon")]
1147 n => Par::rayon(n - 2),
1148 #[cfg(not(feature = "rayon"))]
1149 _ => unreachable!(),
1150 }
1151}
1152
1153#[doc(hidden)]
1154pub mod hacks;
1155
1156pub mod stats;
1158
1159mod non_exhaustive {
1160 #[doc(hidden)]
1161 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1162 #[repr(transparent)]
1163 pub struct NonExhaustive(pub(crate) ());
1164}
1165pub(crate) use non_exhaustive::NonExhaustive;
1166
1167pub trait Auto<T> {
1170 fn auto() -> Self;
1172}
1173
1174pub struct Spec<Config, T> {
1176 pub config: Config,
1178 __marker: core::marker::PhantomData<fn() -> T>,
1179}
1180
1181impl<Config, T> core::ops::Deref for Spec<Config, T> {
1182 type Target = Config;
1183
1184 #[inline]
1185 fn deref(&self) -> &Self::Target {
1186 &self.config
1187 }
1188}
1189
1190impl<Config, T> core::ops::DerefMut for Spec<Config, T> {
1191 #[inline]
1192 fn deref_mut(&mut self) -> &mut Self::Target {
1193 &mut self.config
1194 }
1195}
1196
1197impl<Config: Copy, T> Copy for Spec<Config, T> {}
1198impl<Config: Clone, T> Clone for Spec<Config, T> {
1199 #[inline]
1200 fn clone(&self) -> Self {
1201 Self::new(self.config.clone())
1202 }
1203}
1204impl<Config: core::fmt::Debug, T> core::fmt::Debug for Spec<Config, T> {
1205 #[inline]
1206 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1207 self.config.fmt(f)
1208 }
1209}
1210
1211impl<Config, T> Spec<Config, T> {
1212 #[inline]
1214 pub fn new(config: Config) -> Self {
1215 Spec {
1216 config,
1217 __marker: core::marker::PhantomData,
1218 }
1219 }
1220}
1221
1222impl<T, Config> From<Config> for Spec<Config, T> {
1223 #[inline]
1224 fn from(config: Config) -> Self {
1225 Spec {
1226 config,
1227 __marker: core::marker::PhantomData,
1228 }
1229 }
1230}
1231
1232impl<T, Config: Auto<T>> Default for Spec<Config, T> {
1233 #[inline]
1234 fn default() -> Self {
1235 Spec {
1236 config: Auto::<T>::auto(),
1237 __marker: core::marker::PhantomData,
1238 }
1239 }
1240}
1241
1242mod into_range {
1243 use super::*;
1244
1245 pub trait IntoRange<I> {
1246 type Len<N: Shape>: Shape;
1247
1248 fn into_range(self, min: I, max: I) -> core::ops::Range<I>;
1249 }
1250
1251 impl<I> IntoRange<I> for core::ops::Range<I> {
1252 type Len<N: Shape> = usize;
1253
1254 #[inline]
1255 fn into_range(self, _: I, _: I) -> core::ops::Range<I> {
1256 self
1257 }
1258 }
1259 impl<I> IntoRange<I> for core::ops::RangeFrom<I> {
1260 type Len<N: Shape> = usize;
1261
1262 #[inline]
1263 fn into_range(self, _: I, max: I) -> core::ops::Range<I> {
1264 self.start..max
1265 }
1266 }
1267 impl<I> IntoRange<I> for core::ops::RangeTo<I> {
1268 type Len<N: Shape> = usize;
1269
1270 #[inline]
1271 fn into_range(self, min: I, _: I) -> core::ops::Range<I> {
1272 min..self.end
1273 }
1274 }
1275 impl<I> IntoRange<I> for core::ops::RangeFull {
1276 type Len<N: Shape> = N;
1277
1278 #[inline]
1279 fn into_range(self, min: I, max: I) -> core::ops::Range<I> {
1280 min..max
1281 }
1282 }
1283}
1284
1285mod sort;
1286
1287pub extern crate dyn_stack;
1288pub extern crate faer_traits as traits;
1289pub extern crate reborrow;