1#![cfg_attr(not(feature = "std"), no_std)]
170#![allow(non_snake_case)]
171#![warn(rustdoc::broken_intra_doc_links)]
172extern crate alloc;
173#[cfg(feature = "std")]
174extern crate std;
175#[macro_export]
177macro_rules! make_guard {
178 ($($name:ident),* $(,)?) => {
179 $(#[allow(unused_unsafe)] let $name = unsafe { $crate::generativity::Id::new() };
180 #[allow(unused, unused_unsafe)] let lifetime_brand = unsafe {
181 $crate::generativity::LifetimeBrand::new(&$name) }; #[allow(unused_unsafe)] let
182 $name = unsafe { $crate::generativity::Guard::new($name) };)*
183 };
184}
185macro_rules! repeat_n {
186 ($e:expr, $n:expr) => {
187 iter::repeat_n($e, $n)
188 };
189}
190use core::num::NonZeroUsize;
191use core::sync::atomic::AtomicUsize;
192use equator::{assert, debug_assert};
193use faer_traits::*;
194#[macro_export]
196macro_rules! auto {
197 ($ty:ty $(,)?) => {
198 $crate::Auto::<$ty>::auto()
199 };
200}
201macro_rules! dispatch {
202 ($imp:expr, $ty:ident, $T:ty $(,)?) => {
203 if const { <$T>::IS_NATIVE_C32 } {
204 unsafe {
205 transmute(
206 <ComplexImpl<f32> as ComplexField>::Arch::default()
207 .dispatch(transmute::<_, $ty<ComplexImpl<f32>>>($imp)),
208 )
209 }
210 } else if const { <$T>::IS_NATIVE_C64 } {
211 unsafe {
212 transmute(
213 <ComplexImpl<f64> as ComplexField>::Arch::default()
214 .dispatch(transmute::<_, $ty<ComplexImpl<f64>>>($imp)),
215 )
216 }
217 } else {
218 <$T>::Arch::default().dispatch($imp)
219 }
220 };
221}
222macro_rules! stack_mat {
223 ($name:ident, $m:expr, $n:expr, $A:expr, $N:expr, $T:ty $(,)?) => {
224 let mut __tmp = {
225 #[repr(align(64))]
226 struct __Col<T, const A: usize>([T; A]);
227 struct __Mat<T, const A: usize, const N: usize>([__Col<T, A>; N]);
228 core::mem::MaybeUninit::<__Mat<$T, $A, $N>>::uninit()
229 };
230 let __stack = MemStack::new_any(core::slice::from_mut(&mut __tmp));
231 let mut $name =
232 $crate::linalg::temp_mat_zeroed::<$T, _, _>($m, $n, __stack).0;
233 let mut $name = $crate::mat::AsMatMut::as_mat_mut(&mut $name);
234 };
235 ($name:ident, $m:expr, $n:expr, $T:ty $(,)?) => {
236 stack_mat!($name, $m, $n, $m, $n, $T)
237 };
238}
239#[macro_export]
240#[doc(hidden)]
241macro_rules! __dbg {
242 () => {
243 std::eprintln!("[{}:{}:{}]", std::file!(), std::line!(), std::column!())
244 };
245 ($val:expr $(,)?) => {
246 match $val { tmp => { std::eprintln!("[{}:{}:{}] {} = {:20?}", std::file!(),
247 std::line!(), std::column!(), std::stringify!($val), & tmp); tmp } }
248 };
249 ($($val:expr),+ $(,)?) => {
250 ($($crate::__dbg!($val)),+,)
251 };
252}
253#[cfg(feature = "perf-warn")]
254#[macro_export]
255#[doc(hidden)]
256macro_rules! __perf_warn {
257 ($name:ident) => {{
258 #[inline(always)]
259 #[allow(non_snake_case)]
260 fn $name() -> &'static ::core::sync::atomic::AtomicBool {
261 static $name: ::core::sync::atomic::AtomicBool =
262 ::core::sync::atomic::AtomicBool::new(false);
263 &$name
264 }
265 ::core::matches!(
266 $name().compare_exchange(
267 false,
268 true,
269 ::core::sync::atomic::Ordering::Relaxed,
270 ::core::sync::atomic::Ordering::Relaxed,
271 ),
272 Ok(_)
273 )
274 }};
275}
276#[doc(hidden)]
277#[macro_export]
278macro_rules! with_dim {
279 ($name:ident, $value:expr $(,)?) => {
280 let __val__ = $value; $crate::make_guard!($name); let $name =
281 $crate::utils::bound::Dim::new(__val__, $name);
282 };
283 ({ $(let $name:ident = $value:expr;)* }) => {
284 $(let __val__ = $value; $crate::make_guard!($name); let $name =
285 $crate::utils::bound::Dim::new(__val__, $name);)*
286 };
287}
288#[macro_export]
312macro_rules! zip {
313 ($head:expr $(,)?) => {
314 $crate::linalg::zip::LastEq($crate::linalg::zip::IntoView::into_view($head),
315 ::core::marker::PhantomData)
316 };
317 ($head:expr, $($tail:expr),* $(,)?) => {
318 $crate::linalg::zip::ZipEq::new($crate::linalg::zip::IntoView::into_view($head),
319 $crate::zip!($($tail,)*))
320 };
321}
322#[macro_export]
344macro_rules! Zip {
345 (..$(,)?) => {
346 _
347 };
348 ($head:ty $(,)?) => {
349 $crate::linalg::zip::Last::<$head >
350 };
351 ($head:ty, $($tail:tt)*) => {
352 $crate::linalg::zip::Zip::<$head, $crate::Zip!($($tail)*) >
353 };
354}
355#[macro_export]
375macro_rules! unzip {
376 (..$(,)?) => {
377 _
378 };
379 ($head:pat $(,)?) => {
380 $crate::linalg::zip::Last($head)
381 };
382 ($head:pat, $($tail:tt)*) => {
383 $crate::linalg::zip::Zip($head, $crate::unzip!($($tail)*))
384 };
385}
386#[macro_export]
387#[doc(hidden)]
388macro_rules! __transpose_impl {
389 ([$([$($col:expr),*])*] $($v:expr;)*) => {
390 [$([$($col,)*],)* [$($v,)*]]
391 };
392 ([$([$($col:expr),*])*] $($v0:expr, $($v:expr),*;)*) => {
393 $crate::__transpose_impl!([$([$($col),*])* [$($v0),*]] $($($v),*;)*)
394 };
395}
396#[macro_export]
420macro_rules! mat {
421 () => {
422 { compile_error!("number of columns in the matrix is ambiguous"); }
423 };
424 ($([$($v:expr),* $(,)?]),* $(,)?) => {
425 { let __data = ::core::mem::ManuallyDrop::new($crate::__transpose_impl!([]
426 $($($v),*;)*)); let __data = &* __data; let __ncols = __data.len(); let __nrows =
427 (* __data.get(0).unwrap()).len(); #[allow(unused_unsafe)] unsafe {
428 $crate::mat::Mat::from_fn(__nrows, __ncols, | i, j | ::core::ptr::from_ref(&
429 __data[j] [i]).read()) } }
430 };
431 (
432 @ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (uninit::<$ty:ty >, $($arg:expr),+
433 $(,)?)
434 ) => {
435 let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_uninit::<$ty, _, _
436 > ($($arg,)* $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__);
437 };
438 (
439 @ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (zero::<$ty:ty >, $($arg:expr),+
440 $(,)?)
441 ) => {
442 let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_zeroed::<$ty, _, _
443 > ($($arg,)* $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__);
444 };
445}
446#[macro_export]
457macro_rules! col {
458 ($($v:expr),* $(,)?) => {
459 { let __data = ::core::mem::ManuallyDrop::new([$($v,)*]); let __data = &* __data;
460 let __len = __data.len(); #[allow(unused_unsafe)] unsafe {
461 $crate::col::Col::from_fn(__len, | i | ::core::ptr::from_ref(& __data[i]).read())
462 } }
463 };
464 (
465 @ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (uninit::<$ty:ty >, $($arg:expr),+
466 $(,)?)
467 ) => {
468 let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_uninit::<$ty, _, _
469 > ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0);
470 };
471
472 (
473 @ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (zero::<$ty:ty >, $($arg:expr),+
474 $(,)?)
475 ) => {
476 let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_zeroed::<$ty, _, _
477 > ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0);
478 };
479}
480#[macro_export]
491macro_rules! row {
492 ($($v:expr),* $(,)?) => {
493 { let __data = ::core::mem::ManuallyDrop::new([$($v,)*]); let __data = &* __data;
494 let __len = __data.len(); #[allow(unused_unsafe)] unsafe {
495 $crate::row::Row::from_fn(__len, | i | ::core::ptr::from_ref(& __data[i]).read())
496 } }
497 };
498 (
499 @ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (uninit::<$ty:ty >, $($arg:expr),+
500 $(,)?)
501 ) => {
502 let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_uninit::<$ty, _, _
503 > ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0).transpose_mut();
504 };
505
506 (
507 @ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (zero::<$ty:ty >, $($arg:expr),+
508 $(,)?)
509 ) => {
510 let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_zeroed::<$ty, _, _
511 > ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0).transpose_mut();
512 };
513}
514#[doc(hidden)]
525#[track_caller]
526pub fn concat_impl<T: ComplexField>(
527 blocks: &[&[(mat::MatRef<'_, T>, Conj)]],
528) -> mat::Mat<T> {
529 #[inline(always)]
530 fn count_total_columns<T: ComplexField>(
531 block_row: &[(mat::MatRef<'_, T>, Conj)],
532 ) -> usize {
533 let mut out: usize = 0;
534 for (elem, _) in block_row.iter() {
535 out += elem.ncols();
536 }
537 out
538 }
539 #[inline(always)]
540 #[track_caller]
541 fn count_rows<T: ComplexField>(
542 block_row: &[(mat::MatRef<'_, T>, Conj)],
543 ) -> usize {
544 let mut out: usize = 0;
545 for (i, (e, _)) in block_row.iter().enumerate() {
546 if i == 0 {
547 out = e.nrows();
548 } else {
549 assert!(e.nrows() == out);
550 }
551 }
552 out
553 }
554 let mut n: usize = 0;
555 let mut m: usize = 0;
556 for row in blocks.iter() {
557 n += count_rows(row);
558 }
559 for (i, row) in blocks.iter().enumerate() {
560 let cols = count_total_columns(row);
561 if i == 0 {
562 m = cols;
563 } else {
564 assert!(cols == m);
565 }
566 }
567 let mut mat = mat::Mat::<T>::zeros(n, m);
568 let mut ni: usize = 0;
569 let mut mj: usize;
570 for row in blocks.iter() {
571 mj = 0;
572 for (elem, conj) in row.iter() {
573 let mut dst =
574 mat.as_mut()
575 .submatrix_mut(ni, mj, elem.nrows(), elem.ncols());
576 if *conj == Conj::No {
577 dst.copy_from(elem);
578 } else {
579 dst.copy_from(elem.conjugate());
580 }
581 mj += elem.ncols();
582 }
583 ni += row[0].0.nrows();
584 }
585 mat
586}
587#[macro_export]
595macro_rules! concat {
596 () => {
597 { compile_error!("number of columns in the matrix is ambiguous"); }
598 };
599 ($([$($v:expr),* $(,)?]),* $(,)?) => {
600 { $crate::concat_impl(& [$(& [$(($v).as_ref().__canonicalize(),)*],)*]) }
601 };
602}
603pub mod col;
605pub mod diag;
607#[cfg(feature = "std")]
609pub mod io;
610pub mod linalg;
611pub mod mat;
613#[path = "./operator/mod.rs"]
614pub mod matrix_free;
615pub mod perm;
617pub mod row;
619pub mod sparse;
620pub mod utils;
622pub trait Index: traits::IndexCore + traits::Index + seal::Seal {}
624impl<T: faer_traits::Index<Signed: seal::Seal> + seal::Seal> Index for T {}
625mod seal {
626 pub trait Seal {}
627 impl<T: faer_traits::Seal> Seal for T {}
628 impl Seal for crate::utils::bound::Dim<'_> {}
629 impl<I: crate::Index> Seal for crate::utils::bound::Idx<'_, I> {}
630 impl<I: crate::Index> Seal for crate::utils::bound::IdxInc<'_, I> {}
631 impl<I: crate::Index> Seal for crate::utils::bound::MaybeIdx<'_, I> {}
632 impl<I: crate::Index> Seal for crate::utils::bound::IdxIncOne<I> {}
633 impl<I: crate::Index> Seal for crate::utils::bound::MaybeIdxOne<I> {}
634 impl Seal for crate::utils::bound::One {}
635 impl Seal for crate::utils::bound::Zero {}
636 impl Seal for crate::ContiguousFwd {}
637 impl Seal for crate::ContiguousBwd {}
638}
639pub trait Unbind<I = usize>:
642 Send + Sync + Copy + core::fmt::Debug + seal::Seal
643{
644 unsafe fn new_unbound(idx: I) -> Self;
648 fn unbound(self) -> I;
650}
651pub type Idx<Dim, I = usize> = <Dim as ShapeIdx>::Idx<I>;
653pub type IdxInc<Dim, I = usize> = <Dim as ShapeIdx>::IdxInc<I>;
655pub type MaybeIdx<Dim, I = usize> = <Dim as ShapeIdx>::MaybeIdx<I>;
657pub trait ShapeIdx {
659 type Idx<I: Index>: Unbind<I> + Ord + Eq;
661 type IdxInc<I: Index>: Unbind<I> + Ord + Eq + From<Idx<Self, I>>;
663 type MaybeIdx<I: Index>: Unbind<I::Signed> + Ord + Eq;
665}
666pub trait Shape:
668 Unbind
669 + Ord
670 + ShapeIdx<
671 Idx<usize>: Ord + Eq + PartialOrd<Self>,
672 IdxInc<usize>: Ord + Eq + PartialOrd<Self>,
673 >
674{
675 const IS_BOUND: bool = true;
677 #[inline]
679 fn bind<'n>(self, guard: generativity::Guard<'n>) -> utils::bound::Dim<'n> {
680 utils::bound::Dim::new(self.unbound(), guard)
681 }
682 #[inline]
684 fn cast_idx_slice<I: Index>(slice: &[Idx<Self, I>]) -> &[I] {
685 unsafe { core::slice::from_raw_parts(slice.as_ptr() as _, slice.len()) }
686 }
687 #[inline]
689 fn cast_idx_inc_slice<I: Index>(slice: &[IdxInc<Self, I>]) -> &[I] {
690 unsafe { core::slice::from_raw_parts(slice.as_ptr() as _, slice.len()) }
691 }
692 #[inline(always)]
694 fn start() -> IdxInc<Self> {
695 unsafe { IdxInc::<Self>::new_unbound(0) }
696 }
697 #[inline(always)]
699 fn next(idx: Idx<Self>) -> IdxInc<Self> {
700 unsafe { IdxInc::<Self>::new_unbound(idx.unbound() + 1) }
701 }
702 #[inline(always)]
704 fn end(self) -> IdxInc<Self> {
705 unsafe { IdxInc::<Self>::new_unbound(self.unbound()) }
706 }
707 #[inline(always)]
709 fn idx(self, idx: usize) -> Option<Idx<Self>> {
710 if idx < self.unbound() {
711 Some(unsafe { Idx::<Self>::new_unbound(idx) })
712 } else {
713 None
714 }
715 }
716 #[inline(always)]
718 fn idx_inc(self, idx: usize) -> Option<IdxInc<Self>> {
719 if idx <= self.unbound() {
720 Some(unsafe { IdxInc::<Self>::new_unbound(idx) })
721 } else {
722 None
723 }
724 }
725 #[inline(always)]
727 fn checked_idx(self, idx: usize) -> Idx<Self> {
728 equator::assert!(idx < self.unbound());
729 unsafe { Idx::<Self>::new_unbound(idx) }
730 }
731 #[inline(always)]
733 fn checked_idx_inc(self, idx: usize) -> IdxInc<Self> {
734 equator::assert!(idx <= self.unbound());
735 unsafe { IdxInc::<Self>::new_unbound(idx) }
736 }
737 #[inline(always)]
741 unsafe fn unchecked_idx(self, idx: usize) -> Idx<Self> {
742 equator::debug_assert!(idx < self.unbound());
743 unsafe { Idx::<Self>::new_unbound(idx) }
744 }
745 #[inline(always)]
749 unsafe fn unchecked_idx_inc(self, idx: usize) -> IdxInc<Self> {
750 equator::debug_assert!(idx <= self.unbound());
751 unsafe { IdxInc::<Self>::new_unbound(idx) }
752 }
753 #[inline(always)]
755 fn indices(
756 from: IdxInc<Self>,
757 to: IdxInc<Self>,
758 ) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<Self>>
759 {
760 (from.unbound()..to.unbound()).map(
761 #[inline(always)]
762 |i| unsafe { Idx::<Self>::new_unbound(i) },
763 )
764 }
765}
766impl<T: Send + Sync + Copy + core::fmt::Debug + faer_traits::Seal> Unbind<T>
767 for T
768{
769 #[inline(always)]
770 unsafe fn new_unbound(idx: T) -> Self {
771 idx
772 }
773
774 #[inline(always)]
775 fn unbound(self) -> T {
776 self
777 }
778}
779impl ShapeIdx for usize {
780 type Idx<I: Index> = I;
781 type IdxInc<I: Index> = I;
782 type MaybeIdx<I: Index> = I::Signed;
783}
784impl Shape for usize {
785 const IS_BOUND: bool = false;
786}
787pub trait Stride:
789 seal::Seal + core::fmt::Debug + Copy + Send + Sync + 'static
790{
791 type Rev: Stride<Rev = Self>;
793 fn rev(self) -> Self::Rev;
795 fn element_stride(self) -> isize;
797}
798impl Stride for isize {
799 type Rev = Self;
800
801 #[inline(always)]
802 fn rev(self) -> Self::Rev {
803 -self
804 }
805
806 #[inline(always)]
807 fn element_stride(self) -> isize {
808 self
809 }
810}
811#[derive(Copy, Clone, Debug)]
813pub struct ContiguousFwd;
814#[derive(Copy, Clone, Debug)]
816pub struct ContiguousBwd;
817impl Stride for ContiguousFwd {
818 type Rev = ContiguousBwd;
819
820 #[inline(always)]
821 fn rev(self) -> Self::Rev {
822 ContiguousBwd
823 }
824
825 #[inline(always)]
826 fn element_stride(self) -> isize {
827 1
828 }
829}
830impl Stride for ContiguousBwd {
831 type Rev = ContiguousFwd;
832
833 #[inline(always)]
834 fn rev(self) -> Self::Rev {
835 ContiguousFwd
836 }
837
838 #[inline(always)]
839 fn element_stride(self) -> isize {
840 -1
841 }
842}
843#[derive(Copy, Clone, Debug, PartialEq, Eq)]
845pub enum TryReserveError {
846 CapacityOverflow,
848 AllocError {
850 layout: core::alloc::Layout,
852 },
853}
854#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
856pub enum Conj {
857 No,
859 Yes,
861}
862#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
863pub(crate) enum DiagStatus {
864 Unit,
865 Generic,
866}
867#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
869pub enum Accum {
870 Replace,
872 Add,
874}
875#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
877pub enum Side {
878 Lower,
880 Upper,
882}
883impl Conj {
884 #[inline]
886 pub const fn is_conj(self) -> bool {
887 matches!(self, Conj::Yes)
888 }
889
890 #[inline]
892 pub const fn compose(self, other: Self) -> Self {
893 match (self, other) {
894 (Conj::No, Conj::No) => Conj::No,
895 (Conj::Yes, Conj::Yes) => Conj::No,
896 (Conj::No, Conj::Yes) => Conj::Yes,
897 (Conj::Yes, Conj::No) => Conj::Yes,
898 }
899 }
900
901 #[inline]
904 pub const fn get<T: Conjugate>() -> Self {
905 if T::IS_CANONICAL { Self::No } else { Self::Yes }
906 }
907
908 #[inline]
909 pub(crate) fn apply<T: Conjugate>(value: &T) -> T::Canonical {
910 let value = unsafe { &*(value as *const T as *const T::Canonical) };
911 if const { matches!(Self::get::<T>(), Conj::Yes) } {
912 T::Canonical::conj_impl(value)
913 } else {
914 T::Canonical::copy_impl(value)
915 }
916 }
917
918 #[inline]
919 pub(crate) fn apply_rt<T: ComplexField>(self, value: &T) -> T {
920 if self.is_conj() {
921 T::conj_impl(value)
922 } else {
923 T::copy_impl(value)
924 }
925 }
926}
927#[derive(Copy, Clone, Debug, PartialEq, Eq)]
929pub enum Par {
930 Seq,
932 #[cfg(feature = "rayon")]
935 Rayon(NonZeroUsize),
936}
937impl Par {
938 #[inline]
941 #[cfg(feature = "rayon")]
942 pub fn rayon(nthreads: usize) -> Self {
943 if nthreads == 0 {
944 Self::Rayon(
945 NonZeroUsize::new(rayon::current_num_threads()).unwrap(),
946 )
947 } else {
948 Self::Rayon(NonZeroUsize::new(nthreads).unwrap())
949 }
950 }
951
952 #[inline]
955 pub fn degree(&self) -> usize {
956 utils::thread::parallelism_degree(*self)
957 }
958}
959#[allow(non_camel_case_types)]
960pub type c32 = traits::c32;
962#[allow(non_camel_case_types)]
963pub type c64 = traits::c64;
965#[allow(non_camel_case_types)]
966pub type cx128 = traits::cx128;
968#[allow(non_camel_case_types)]
969pub type fx128 = traits::fx128;
971pub use col::{Col, ColMut, ColRef};
972pub use mat::{Mat, MatMut, MatRef};
973pub use row::{Row, RowMut, RowRef};
974#[allow(unused_imports, dead_code)]
975mod internal_prelude {
976 pub use crate::simd_iter;
977
978 pub trait DivCeil: Sized {
979 fn msrv_div_ceil(self, rhs: Self) -> Self;
980 fn msrv_next_multiple_of(self, rhs: Self) -> Self;
981 fn msrv_checked_next_multiple_of(self, rhs: Self) -> Option<Self>;
982 }
983 impl DivCeil for usize {
984 #[inline]
985 fn msrv_div_ceil(self, rhs: Self) -> Self {
986 let d = self / rhs;
987 let r = self % rhs;
988 if r > 0 { d + 1 } else { d }
989 }
990
991 #[inline]
992 fn msrv_next_multiple_of(self, rhs: Self) -> Self {
993 match self % rhs {
994 0 => self,
995 r => self + (rhs - r),
996 }
997 }
998
999 #[inline]
1000 fn msrv_checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
1001 {
1002 match self.checked_rem(rhs)? {
1003 0 => Some(self),
1004 r => self.checked_add(rhs - r),
1005 }
1006 }
1007 }
1008 }
1009 pub(crate) use crate::col::{Col, ColMut, ColRef};
1010 pub(crate) use crate::diag::{Diag, DiagMut, DiagRef};
1011 pub(crate) use crate::hacks::transmute;
1012 pub(crate) use crate::linalg::{
1013 self, temp_mat_scratch, temp_mat_uninit, temp_mat_zeroed,
1014 };
1015 pub(crate) use crate::mat::{
1016 AsMat, AsMatMut, AsMatRef, Mat, MatMut, MatRef,
1017 };
1018 pub(crate) use crate::perm::{Perm, PermRef};
1019 pub(crate) use crate::prelude::*;
1020 pub(crate) use crate::row::{AsRowMut, AsRowRef, Row, RowMut, RowRef};
1021 pub(crate) use crate::utils::bound::{Array, Dim, Idx, IdxInc, MaybeIdx};
1022 pub(crate) use crate::utils::simd::SimdCtx;
1023 pub(crate) use crate::{Auto, NonExhaustive, Side, Spec};
1024 pub use faer_traits::ext::*;
1025 pub use faer_traits::math_utils::*;
1026 pub use faer_traits::{
1027 ComplexField, ComplexImpl, ComplexImplConj, Conjugate, Index,
1028 IndexCore, Real, RealField, SignedIndex, SimdArch, Symbolic,
1029 };
1030 pub use num_complex::Complex;
1031 #[cfg(test)]
1032 pub(crate) use std::dbg;
1033 #[cfg(test)]
1034 pub(crate) use {alloc::boxed::Box, alloc::vec, alloc::vec::Vec};
1035 #[inline]
1036 pub fn simd_align(i: usize) -> usize {
1037 i.wrapping_neg()
1038 }
1039 pub(crate) use self::{unzip as uz, zip as z};
1040 pub(crate) use crate::{
1041 Accum, Conj, ContiguousBwd, ContiguousFwd, DiagStatus, Par, Shape,
1042 Stride, Unbind, make_guard, unzip, zip,
1043 };
1044 pub use dyn_stack::{MemStack, StackReq, alloc as alloca};
1045 pub use equator::{
1046 assert, assert as Assert, debug_assert, debug_assert as DebugAssert,
1047 };
1048 pub use reborrow::*;
1049}
1050#[allow(unused_imports)]
1051pub(crate) mod internal_prelude_sp {
1052 pub(crate) use crate::internal_prelude::*;
1053 pub(crate) use crate::sparse::{
1054 FaerError, NONE, Pair, SparseColMat, SparseColMatMut, SparseColMatRef,
1055 SparseRowMat, SparseRowMatMut, SparseRowMatRef, SymbolicSparseColMat,
1056 SymbolicSparseColMatRef, SymbolicSparseRowMat, SymbolicSparseRowMatRef,
1057 Triplet, csc_numeric, csc_symbolic, csr_numeric, csr_symbolic,
1058 linalg as linalg_sp, try_collect, try_zeroed, windows2,
1059 };
1060 pub(crate) use core::cell::Cell;
1061 pub(crate) use core::iter;
1062 pub(crate) use dyn_stack::MemBuffer;
1063}
1064pub mod prelude {
1066 #[cfg(feature = "linalg")]
1067 pub use super::linalg::solvers::{DenseSolve, Solve, SolveLstsq};
1068 #[cfg(feature = "sparse")]
1069 pub use super::prelude_sp::*;
1070 pub use super::{Par, Scale, c32, c64, col, mat, row, unzip, zip};
1071 pub use col::{Col, ColMut, ColRef};
1072 pub use mat::{Mat, MatMut, MatRef};
1073 pub use reborrow::{IntoConst, Reborrow, ReborrowMut};
1074 pub use row::{Row, RowMut, RowRef};
1075 #[inline]
1077 pub fn default<T: Default>() -> T {
1078 Default::default()
1079 }
1080}
1081#[cfg(feature = "sparse")]
1082mod prelude_sp {
1083 use crate::sparse;
1084 pub use sparse::{
1085 SparseColMat, SparseColMatMut, SparseColMatRef, SparseRowMat,
1086 SparseRowMatMut, SparseRowMatRef,
1087 };
1088}
1089#[derive(Copy, Clone, Debug)]
1091#[repr(transparent)]
1092pub struct Scale<T>(pub T);
1093impl<T> Scale<T> {
1094 #[inline(always)]
1096 pub fn from_ref(value: &T) -> &Self {
1097 unsafe { &*(value as *const T as *const Self) }
1098 }
1099
1100 #[inline(always)]
1103 pub fn from_mut(value: &mut T) -> &mut Self {
1104 unsafe { &mut *(value as *mut T as *mut Self) }
1105 }
1106}
1107static GLOBAL_PARALLELISM: AtomicUsize = {
1113 #[cfg(all(not(miri), feature = "rayon"))]
1114 {
1115 AtomicUsize::new(2)
1116 }
1117 #[cfg(not(all(not(miri), feature = "rayon")))]
1118 {
1119 AtomicUsize::new(1)
1120 }
1121};
1122pub fn disable_global_parallelism() {
1124 GLOBAL_PARALLELISM.store(0, core::sync::atomic::Ordering::Relaxed);
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#[track_caller]
1140pub fn get_global_parallelism() -> Par {
1141 let value = GLOBAL_PARALLELISM.load(core::sync::atomic::Ordering::Relaxed);
1142 match value {
1143 0 => panic!("Global parallelism is disabled."),
1144 1 => Par::Seq,
1145 #[cfg(feature = "rayon")]
1146 n => Par::rayon(n - 2),
1147 #[cfg(not(feature = "rayon"))]
1148 _ => unreachable!(),
1149 }
1150}
1151#[doc(hidden)]
1152pub mod hacks;
1153pub mod stats;
1155mod non_exhaustive {
1156 #[doc(hidden)]
1157 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
1158 #[repr(transparent)]
1159 pub struct NonExhaustive(pub(crate) ());
1160}
1161pub(crate) use non_exhaustive::NonExhaustive;
1162pub trait Auto<T> {
1165 fn auto() -> Self;
1167}
1168pub struct Spec<Config, T> {
1171 pub config: Config,
1173 __marker: core::marker::PhantomData<fn() -> T>,
1174}
1175impl<Config, T> core::ops::Deref for Spec<Config, T> {
1176 type Target = Config;
1177
1178 #[inline]
1179 fn deref(&self) -> &Self::Target {
1180 &self.config
1181 }
1182}
1183impl<Config, T> core::ops::DerefMut for Spec<Config, T> {
1184 #[inline]
1185 fn deref_mut(&mut self) -> &mut Self::Target {
1186 &mut self.config
1187 }
1188}
1189impl<Config: Copy, T> Copy for Spec<Config, T> {}
1190impl<Config: Clone, T> Clone for Spec<Config, T> {
1191 #[inline]
1192 fn clone(&self) -> Self {
1193 Self::new(self.config.clone())
1194 }
1195}
1196impl<Config: core::fmt::Debug, T> core::fmt::Debug for Spec<Config, T> {
1197 #[inline]
1198 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1199 self.config.fmt(f)
1200 }
1201}
1202impl<Config, T> Spec<Config, T> {
1203 #[inline]
1205 pub fn new(config: Config) -> Self {
1206 Spec {
1207 config,
1208 __marker: core::marker::PhantomData,
1209 }
1210 }
1211}
1212impl<T, Config> From<Config> for Spec<Config, T> {
1213 #[inline]
1214 fn from(config: Config) -> Self {
1215 Spec {
1216 config,
1217 __marker: core::marker::PhantomData,
1218 }
1219 }
1220}
1221impl<T, Config: Auto<T>> Default for Spec<Config, T> {
1222 #[inline]
1223 fn default() -> Self {
1224 Spec {
1225 config: Auto::<T>::auto(),
1226 __marker: core::marker::PhantomData,
1227 }
1228 }
1229}
1230mod into_range {
1231 use super::*;
1232 pub trait IntoRange<I> {
1233 type Len<N: Shape>: Shape;
1234 fn into_range(self, min: I, max: I) -> core::ops::Range<I>;
1235 }
1236 impl<I> IntoRange<I> for core::ops::Range<I> {
1237 type Len<N: Shape> = usize;
1238
1239 #[inline]
1240 fn into_range(self, _: I, _: I) -> core::ops::Range<I> {
1241 self
1242 }
1243 }
1244 impl<I> IntoRange<I> for core::ops::RangeFrom<I> {
1245 type Len<N: Shape> = usize;
1246
1247 #[inline]
1248 fn into_range(self, _: I, max: I) -> core::ops::Range<I> {
1249 self.start..max
1250 }
1251 }
1252 impl<I> IntoRange<I> for core::ops::RangeTo<I> {
1253 type Len<N: Shape> = usize;
1254
1255 #[inline]
1256 fn into_range(self, min: I, _: I) -> core::ops::Range<I> {
1257 min..self.end
1258 }
1259 }
1260 impl<I> IntoRange<I> for core::ops::RangeFull {
1261 type Len<N: Shape> = N;
1262
1263 #[inline]
1264 fn into_range(self, min: I, max: I) -> core::ops::Range<I> {
1265 min..max
1266 }
1267 }
1268}
1269mod sort;
1270pub extern crate dyn_stack;
1271pub extern crate faer_traits as traits;
1272#[doc(hidden)]
1273pub extern crate generativity;
1274pub extern crate num_complex as complex;
1275#[cfg(feature = "rand")]
1276#[cfg_attr(docs_rs, doc(cfg(feature = "rand")))]
1277pub extern crate rand;
1278pub extern crate reborrow;
1279
1280extern crate self as faer;
1281
1282#[macro_export]
1283#[doc(hidden)]
1284macro_rules! simd_iter {
1285 (for ($batch_id:tt, $i:pat $(,)?) in [$indices:expr; $batch_size:expr] $b:block $(,)?) => {#[allow(non_upper_case_globals, unconditional_panic)] 'out:{
1286 let (__head__, __body_batch__, __body_item__, __tail__) = &$indices;
1287 let __body_batch__ = __body_batch__.clone();
1288 let mut __body_item__ = __body_item__.clone();
1289 const {
1290 ::core::assert!($batch_size > 0);
1291 ::core::assert!($batch_size <= 8);
1292 }
1293 {
1294 if const { $batch_size == 1 } {if $batch_size == 1 { const $batch_id: usize = 0; if let &Some($i) = __head__ $b; }}
1295 if const { $batch_size == 2 } {if $batch_size == 2 { const $batch_id: usize = 1; if let &Some($i) = __head__ $b; }}
1296 if const { $batch_size == 3 } {if $batch_size == 3 { const $batch_id: usize = 2; if let &Some($i) = __head__ $b; }}
1297 if const { $batch_size == 4 } {if $batch_size == 4 { const $batch_id: usize = 3; if let &Some($i) = __head__ $b; }}
1298 if const { $batch_size == 5 } {if $batch_size == 5 { const $batch_id: usize = 4; if let &Some($i) = __head__ $b; }}
1299 if const { $batch_size == 6 } {if $batch_size == 6 { const $batch_id: usize = 5; if let &Some($i) = __head__ $b; }}
1300 if const { $batch_size == 7 } {if $batch_size == 7 { const $batch_id: usize = 6; if let &Some($i) = __head__ $b; }}
1301 if const { $batch_size == 8 } {if $batch_size == 8 { const $batch_id: usize = 7; if let &Some($i) = __head__ $b; }}
1302 }
1303 for __i__ in __body_batch__ {
1304 let __i__: [_; $batch_size] = __i__;
1305 let __i__ = __i__.as_slice();
1306 ::core::assert!(__i__.len() == $batch_size);
1307
1308 {
1309 if const { $batch_size > 0 } {if __i__.len() > 0 { const $batch_id: usize = 0; let $i = __i__[0]; $b }}
1310 if const { $batch_size > 1 } {if __i__.len() > 1 { const $batch_id: usize = 1; let $i = __i__[1]; $b }}
1311 if const { $batch_size > 2 } {if __i__.len() > 2 { const $batch_id: usize = 2; let $i = __i__[2]; $b }}
1312 if const { $batch_size > 3 } {if __i__.len() > 3 { const $batch_id: usize = 3; let $i = __i__[3]; $b }}
1313 if const { $batch_size > 4 } {if __i__.len() > 4 { const $batch_id: usize = 4; let $i = __i__[4]; $b }}
1314 if const { $batch_size > 5 } {if __i__.len() > 5 { const $batch_id: usize = 5; let $i = __i__[5]; $b }}
1315 if const { $batch_size > 6 } {if __i__.len() > 6 { const $batch_id: usize = 6; let $i = __i__[6]; $b }}
1316 if const { $batch_size > 7 } {if __i__.len() > 7 { const $batch_id: usize = 7; let $i = __i__[7]; $b }}
1317 }
1318 };
1319
1320 {
1321 if const { $batch_size > 0 } { if $batch_size > 0 { const $batch_id: usize = 0; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1322 if const { $batch_size > 1 } { if $batch_size > 1 { const $batch_id: usize = 1; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1323 if const { $batch_size > 2 } { if $batch_size > 2 { const $batch_id: usize = 2; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1324 if const { $batch_size > 3 } { if $batch_size > 3 { const $batch_id: usize = 3; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1325 if const { $batch_size > 4 } { if $batch_size > 4 { const $batch_id: usize = 4; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1326 if const { $batch_size > 5 } { if $batch_size > 5 { const $batch_id: usize = 5; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1327 if const { $batch_size > 6 } { if $batch_size > 6 { const $batch_id: usize = 6; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1328 if const { $batch_size > 7 } { if $batch_size > 7 { const $batch_id: usize = 7; if let Some($i) = __body_item__.next() $b else { if let &Some($i) = __tail__ $b; break 'out; } } }
1329 }
1330 }};
1331 (for $i:pat in [$indices:expr] $b:block $(,)?) => {#[allow(non_upper_case_globals)]{
1332 let (__head__, __body__, __tail__) = &$indices;
1333 if let &Some($i) = __head__ $b;
1334 for $i in __body__.clone() $b;
1335 if let &Some($i) = __tail__ $b;
1336 }};
1337}