#![cfg_attr(not(feature = "std"), no_std)]
#![allow(non_snake_case)]
#![warn(rustdoc::broken_intra_doc_links)]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std;
#[macro_export]
macro_rules! make_guard {
($($name:ident),* $(,)?) => {
$(#[allow(unused_unsafe)] let $name = unsafe { $crate::generativity::Id::new() };
#[allow(unused, unused_unsafe)] let lifetime_brand = unsafe {
$crate::generativity::LifetimeBrand::new(&$name) }; #[allow(unused_unsafe)] let
$name = unsafe { $crate::generativity::Guard::new($name) };)*
};
}
macro_rules! repeat_n {
($e:expr, $n:expr) => {
iter::repeat_n($e, $n)
};
}
use core::num::NonZeroUsize;
use core::sync::atomic::AtomicUsize;
use equator::{assert, debug_assert};
use faer_traits::*;
#[macro_export]
macro_rules! auto {
($ty:ty $(,)?) => {
$crate::Auto::<$ty>::auto()
};
}
macro_rules! dispatch {
($imp:expr, $ty:ident, $T:ty $(,)?) => {
if const { <$T>::IS_NATIVE_C32 } {
unsafe {
transmute(
<ComplexImpl<f32> as ComplexField>::Arch::default()
.dispatch(transmute::<_, $ty<ComplexImpl<f32>>>($imp)),
)
}
} else if const { <$T>::IS_NATIVE_C64 } {
unsafe {
transmute(
<ComplexImpl<f64> as ComplexField>::Arch::default()
.dispatch(transmute::<_, $ty<ComplexImpl<f64>>>($imp)),
)
}
} else {
<$T>::Arch::default().dispatch($imp)
}
};
}
macro_rules! stack_mat {
($name:ident, $m:expr, $n:expr, $A:expr, $N:expr, $T:ty $(,)?) => {
let mut __tmp = {
#[repr(align(64))]
struct __Col<T, const A: usize>([T; A]);
struct __Mat<T, const A: usize, const N: usize>([__Col<T, A>; N]);
core::mem::MaybeUninit::<__Mat<$T, $A, $N>>::uninit()
};
let __stack = MemStack::new_any(core::slice::from_mut(&mut __tmp));
let mut $name =
$crate::linalg::temp_mat_zeroed::<$T, _, _>($m, $n, __stack).0;
let mut $name = $crate::mat::AsMatMut::as_mat_mut(&mut $name);
};
($name:ident, $m:expr, $n:expr, $T:ty $(,)?) => {
stack_mat!($name, $m, $n, $m, $n, $T)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __dbg {
() => {
std::eprintln!("[{}:{}:{}]", std::file!(), std::line!(), std::column!())
};
($val:expr $(,)?) => {
match $val { tmp => { std::eprintln!("[{}:{}:{}] {} = {:16.12?}", std::file!(),
std::line!(), std::column!(), std::stringify!($val), & tmp); tmp } }
};
($($val:expr),+ $(,)?) => {
($($crate::__dbg!($val)),+,)
};
}
#[cfg(feature = "perf-warn")]
#[macro_export]
#[doc(hidden)]
macro_rules! __perf_warn {
($name:ident) => {{
#[inline(always)]
#[allow(non_snake_case)]
fn $name() -> &'static ::core::sync::atomic::AtomicBool {
static $name: ::core::sync::atomic::AtomicBool =
::core::sync::atomic::AtomicBool::new(false);
&$name
}
::core::matches!(
$name().compare_exchange(
false,
true,
::core::sync::atomic::Ordering::Relaxed,
::core::sync::atomic::Ordering::Relaxed,
),
Ok(_)
)
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! with_dim {
($name:ident, $value:expr $(,)?) => {
let __val__ = $value; $crate::make_guard!($name); let $name =
$crate::utils::bound::Dim::new(__val__, $name);
};
({ $(let $name:ident = $value:expr;)* }) => {
$(let __val__ = $value; $crate::make_guard!($name); let $name =
$crate::utils::bound::Dim::new(__val__, $name);)*
};
}
#[macro_export]
macro_rules! zip {
($head:expr $(,)?) => {
$crate::linalg::zip::LastEq($crate::linalg::zip::IntoView::into_view($head),
::core::marker::PhantomData)
};
($head:expr, $($tail:expr),* $(,)?) => {
$crate::linalg::zip::ZipEq::new($crate::linalg::zip::IntoView::into_view($head),
$crate::zip!($($tail,)*))
};
}
#[macro_export]
macro_rules! Zip {
(..$(,)?) => {
_
};
($head:ty $(,)?) => {
$crate::linalg::zip::Last::<$head >
};
($head:ty, $($tail:tt)*) => {
$crate::linalg::zip::Zip::<$head, $crate::Zip!($($tail)*) >
};
}
#[macro_export]
macro_rules! unzip {
(..$(,)?) => {
_
};
($head:pat $(,)?) => {
$crate::linalg::zip::Last($head)
};
($head:pat, $($tail:tt)*) => {
$crate::linalg::zip::Zip($head, $crate::unzip!($($tail)*))
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __transpose_impl {
([$([$($col:expr),*])*] $($v:expr;)*) => {
[$([$($col,)*],)* [$($v,)*]]
};
([$([$($col:expr),*])*] $($v0:expr, $($v:expr),*;)*) => {
$crate::__transpose_impl!([$([$($col),*])* [$($v0),*]] $($($v),*;)*)
};
}
#[macro_export]
macro_rules! mat {
() => {
{ compile_error!("number of columns in the matrix is ambiguous"); }
};
($([$($v:expr),* $(,)?]),* $(,)?) => {
{ let __data = ::core::mem::ManuallyDrop::new($crate::__transpose_impl!([]
$($($v),*;)*)); let __data = &* __data; let __ncols = __data.len(); let __nrows =
(* __data.get(0).unwrap()).len(); #[allow(unused_unsafe)] unsafe {
$crate::mat::Mat::from_fn(__nrows, __ncols, | i, j | ::core::ptr::from_ref(&
__data[j] [i]).read()) } }
};
(
@ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (uninit::<$ty:ty >, $($arg:expr),+
$(,)?)
) => {
let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_uninit::<$ty, _, _
> ($($arg,)* $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__);
};
(
@ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (zero::<$ty:ty >, $($arg:expr),+
$(,)?)
) => {
let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_zeroed::<$ty, _, _
> ($($arg,)* $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__);
};
}
#[macro_export]
macro_rules! col {
($($v:expr),* $(,)?) => {
{ let __data = ::core::mem::ManuallyDrop::new([$($v,)*]); let __data = &* __data;
let __len = __data.len(); #[allow(unused_unsafe)] unsafe {
$crate::col::Col::from_fn(__len, | i | ::core::ptr::from_ref(& __data[i]).read())
} }
};
(
@ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (uninit::<$ty:ty >, $($arg:expr),+
$(,)?)
) => {
let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_uninit::<$ty, _, _
> ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0);
};
(
@ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (zero::<$ty:ty >, $($arg:expr),+
$(,)?)
) => {
let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_zeroed::<$ty, _, _
> ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0);
};
}
#[macro_export]
macro_rules! row {
($($v:expr),* $(,)?) => {
{ let __data = ::core::mem::ManuallyDrop::new([$($v,)*]); let __data = &* __data;
let __len = __data.len(); #[allow(unused_unsafe)] unsafe {
$crate::row::Row::from_fn(__len, | i | ::core::ptr::from_ref(& __data[i]).read())
} }
};
(
@ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (uninit::<$ty:ty >, $($arg:expr),+
$(,)?)
) => {
let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_uninit::<$ty, _, _
> ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0).transpose_mut();
};
(
@ alloc $($unsafe:ident)? ($stack:ident) ($var:pat) (zero::<$ty:ty >, $($arg:expr),+
$(,)?)
) => {
let (mut __mat__, $stack) = $($unsafe)? { $crate::linalg::temp_mat_zeroed::<$ty, _, _
> ($($arg,)* 1, $stack,) }; let $var = $crate::mat::AsMatMut::as_mat_mut(&mut __mat__).col_mut(0).transpose_mut();
};
}
#[doc(hidden)]
#[track_caller]
pub fn concat_impl<T: ComplexField>(
blocks: &[&[(mat::MatRef<'_, T>, Conj)]],
) -> mat::Mat<T> {
#[inline(always)]
fn count_total_columns<T: ComplexField>(
block_row: &[(mat::MatRef<'_, T>, Conj)],
) -> usize {
let mut out: usize = 0;
for (elem, _) in block_row.iter() {
out += elem.ncols();
}
out
}
#[inline(always)]
#[track_caller]
fn count_rows<T: ComplexField>(
block_row: &[(mat::MatRef<'_, T>, Conj)],
) -> usize {
let mut out: usize = 0;
for (i, (e, _)) in block_row.iter().enumerate() {
if i == 0 {
out = e.nrows();
} else {
assert!(e.nrows() == out);
}
}
out
}
let mut n: usize = 0;
let mut m: usize = 0;
for row in blocks.iter() {
n += count_rows(row);
}
for (i, row) in blocks.iter().enumerate() {
let cols = count_total_columns(row);
if i == 0 {
m = cols;
} else {
assert!(cols == m);
}
}
let mut mat = mat::Mat::<T>::zeros(n, m);
let mut ni: usize = 0;
let mut mj: usize;
for row in blocks.iter() {
mj = 0;
for (elem, conj) in row.iter() {
let mut dst =
mat.as_mut()
.submatrix_mut(ni, mj, elem.nrows(), elem.ncols());
if *conj == Conj::No {
dst.copy_from(elem);
} else {
dst.copy_from(elem.conjugate());
}
mj += elem.ncols();
}
ni += row[0].0.nrows();
}
mat
}
#[macro_export]
macro_rules! concat {
() => {
{ compile_error!("number of columns in the matrix is ambiguous"); }
};
($([$($v:expr),* $(,)?]),* $(,)?) => {
{ $crate::concat_impl(& [$(& [$(($v).as_ref().__canonicalize(),)*],)*]) }
};
}
pub mod col;
pub mod diag;
#[cfg(feature = "std")]
pub mod io;
pub mod linalg;
pub mod mat;
#[path = "./operator/mod.rs"]
pub mod matrix_free;
pub mod perm;
pub mod row;
pub mod sparse;
pub mod utils;
pub trait Index: traits::IndexCore + traits::Index + seal::Seal {}
impl<T: faer_traits::Index<Signed: seal::Seal> + seal::Seal> Index for T {}
mod seal {
pub trait Seal {}
impl<T: faer_traits::Seal> Seal for T {}
impl Seal for crate::utils::bound::Dim<'_> {}
impl<I: crate::Index> Seal for crate::utils::bound::Idx<'_, I> {}
impl<I: crate::Index> Seal for crate::utils::bound::IdxInc<'_, I> {}
impl<I: crate::Index> Seal for crate::utils::bound::MaybeIdx<'_, I> {}
impl<I: crate::Index> Seal for crate::utils::bound::IdxIncOne<I> {}
impl<I: crate::Index> Seal for crate::utils::bound::MaybeIdxOne<I> {}
impl Seal for crate::utils::bound::One {}
impl Seal for crate::utils::bound::Zero {}
impl Seal for crate::ContiguousFwd {}
impl Seal for crate::ContiguousBwd {}
}
pub trait Unbind<I = usize>:
Send + Sync + Copy + core::fmt::Debug + seal::Seal
{
unsafe fn new_unbound(idx: I) -> Self;
fn unbound(self) -> I;
}
pub type Idx<Dim, I = usize> = <Dim as ShapeIdx>::Idx<I>;
pub type IdxInc<Dim, I = usize> = <Dim as ShapeIdx>::IdxInc<I>;
pub type MaybeIdx<Dim, I = usize> = <Dim as ShapeIdx>::MaybeIdx<I>;
pub trait ShapeIdx {
type Idx<I: Index>: Unbind<I> + Ord + Eq;
type IdxInc<I: Index>: Unbind<I> + Ord + Eq + From<Idx<Self, I>>;
type MaybeIdx<I: Index>: Unbind<I::Signed> + Ord + Eq;
}
pub trait Shape:
Unbind
+ Ord
+ ShapeIdx<
Idx<usize>: Ord + Eq + PartialOrd<Self>,
IdxInc<usize>: Ord + Eq + PartialOrd<Self>,
>
{
const IS_BOUND: bool = true;
#[inline]
fn bind<'n>(self, guard: generativity::Guard<'n>) -> utils::bound::Dim<'n> {
utils::bound::Dim::new(self.unbound(), guard)
}
#[inline]
fn cast_idx_slice<I: Index>(slice: &[Idx<Self, I>]) -> &[I] {
unsafe { core::slice::from_raw_parts(slice.as_ptr() as _, slice.len()) }
}
#[inline]
fn cast_idx_inc_slice<I: Index>(slice: &[IdxInc<Self, I>]) -> &[I] {
unsafe { core::slice::from_raw_parts(slice.as_ptr() as _, slice.len()) }
}
#[inline(always)]
fn start() -> IdxInc<Self> {
unsafe { IdxInc::<Self>::new_unbound(0) }
}
#[inline(always)]
fn next(idx: Idx<Self>) -> IdxInc<Self> {
unsafe { IdxInc::<Self>::new_unbound(idx.unbound() + 1) }
}
#[inline(always)]
fn end(self) -> IdxInc<Self> {
unsafe { IdxInc::<Self>::new_unbound(self.unbound()) }
}
#[inline(always)]
fn idx(self, idx: usize) -> Option<Idx<Self>> {
if idx < self.unbound() {
Some(unsafe { Idx::<Self>::new_unbound(idx) })
} else {
None
}
}
#[inline(always)]
fn idx_inc(self, idx: usize) -> Option<IdxInc<Self>> {
if idx <= self.unbound() {
Some(unsafe { IdxInc::<Self>::new_unbound(idx) })
} else {
None
}
}
#[inline(always)]
fn checked_idx(self, idx: usize) -> Idx<Self> {
equator::assert!(idx < self.unbound());
unsafe { Idx::<Self>::new_unbound(idx) }
}
#[inline(always)]
fn checked_idx_inc(self, idx: usize) -> IdxInc<Self> {
equator::assert!(idx <= self.unbound());
unsafe { IdxInc::<Self>::new_unbound(idx) }
}
#[inline(always)]
unsafe fn unchecked_idx(self, idx: usize) -> Idx<Self> {
equator::debug_assert!(idx < self.unbound());
unsafe { Idx::<Self>::new_unbound(idx) }
}
#[inline(always)]
unsafe fn unchecked_idx_inc(self, idx: usize) -> IdxInc<Self> {
equator::debug_assert!(idx <= self.unbound());
unsafe { IdxInc::<Self>::new_unbound(idx) }
}
#[inline(always)]
fn indices(
from: IdxInc<Self>,
to: IdxInc<Self>,
) -> impl Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<Self>>
{
(from.unbound()..to.unbound()).map(
#[inline(always)]
|i| unsafe { Idx::<Self>::new_unbound(i) },
)
}
}
impl<T: Send + Sync + Copy + core::fmt::Debug + faer_traits::Seal> Unbind<T>
for T
{
#[inline(always)]
unsafe fn new_unbound(idx: T) -> Self {
idx
}
#[inline(always)]
fn unbound(self) -> T {
self
}
}
impl ShapeIdx for usize {
type Idx<I: Index> = I;
type IdxInc<I: Index> = I;
type MaybeIdx<I: Index> = I::Signed;
}
impl Shape for usize {
const IS_BOUND: bool = false;
}
pub trait Stride:
seal::Seal + core::fmt::Debug + Copy + Send + Sync + 'static
{
type Rev: Stride<Rev = Self>;
fn rev(self) -> Self::Rev;
fn element_stride(self) -> isize;
}
impl Stride for isize {
type Rev = Self;
#[inline(always)]
fn rev(self) -> Self::Rev {
-self
}
#[inline(always)]
fn element_stride(self) -> isize {
self
}
}
#[derive(Copy, Clone, Debug)]
pub struct ContiguousFwd;
#[derive(Copy, Clone, Debug)]
pub struct ContiguousBwd;
impl Stride for ContiguousFwd {
type Rev = ContiguousBwd;
#[inline(always)]
fn rev(self) -> Self::Rev {
ContiguousBwd
}
#[inline(always)]
fn element_stride(self) -> isize {
1
}
}
impl Stride for ContiguousBwd {
type Rev = ContiguousFwd;
#[inline(always)]
fn rev(self) -> Self::Rev {
ContiguousFwd
}
#[inline(always)]
fn element_stride(self) -> isize {
-1
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum TryReserveError {
CapacityOverflow,
AllocError {
layout: core::alloc::Layout,
},
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Conj {
No,
Yes,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) enum DiagStatus {
Unit,
Generic,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Accum {
Replace,
Add,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum Side {
Lower,
Upper,
}
impl Conj {
#[inline]
pub const fn is_conj(self) -> bool {
matches!(self, Conj::Yes)
}
#[inline]
pub const fn compose(self, other: Self) -> Self {
match (self, other) {
(Conj::No, Conj::No) => Conj::No,
(Conj::Yes, Conj::Yes) => Conj::No,
(Conj::No, Conj::Yes) => Conj::Yes,
(Conj::Yes, Conj::No) => Conj::Yes,
}
}
#[inline]
pub const fn get<T: Conjugate>() -> Self {
if T::IS_CANONICAL { Self::No } else { Self::Yes }
}
#[inline]
pub(crate) fn apply<T: Conjugate>(value: &T) -> T::Canonical {
let value = unsafe { &*(value as *const T as *const T::Canonical) };
if const { matches!(Self::get::<T>(), Conj::Yes) } {
T::Canonical::conj_impl(value)
} else {
T::Canonical::copy_impl(value)
}
}
#[inline]
pub(crate) fn apply_rt<T: ComplexField>(self, value: &T) -> T {
if self.is_conj() {
T::conj_impl(value)
} else {
T::copy_impl(value)
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Par {
Seq,
#[cfg(feature = "rayon")]
Rayon(NonZeroUsize),
}
impl Par {
#[inline]
#[cfg(feature = "rayon")]
pub fn rayon(nthreads: usize) -> Self {
if nthreads == 0 {
Self::Rayon(
NonZeroUsize::new(rayon::current_num_threads()).unwrap(),
)
} else {
Self::Rayon(NonZeroUsize::new(nthreads).unwrap())
}
}
#[inline]
pub fn degree(&self) -> usize {
utils::thread::parallelism_degree(*self)
}
}
#[allow(non_camel_case_types)]
pub type c32 = traits::c32;
#[allow(non_camel_case_types)]
pub type c64 = traits::c64;
#[allow(non_camel_case_types)]
pub type cx128 = traits::cx128;
#[allow(non_camel_case_types)]
pub type fx128 = traits::fx128;
pub use col::{Col, ColMut, ColRef};
pub use mat::{Mat, MatMut, MatRef};
pub use row::{Row, RowMut, RowRef};
#[allow(unused_imports, dead_code)]
mod internal_prelude {
pub use crate::simd_iter;
pub trait DivCeil: Sized {
fn msrv_div_ceil(self, rhs: Self) -> Self;
fn msrv_next_multiple_of(self, rhs: Self) -> Self;
fn msrv_checked_next_multiple_of(self, rhs: Self) -> Option<Self>;
}
impl DivCeil for usize {
#[inline]
fn msrv_div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
if r > 0 { d + 1 } else { d }
}
#[inline]
fn msrv_next_multiple_of(self, rhs: Self) -> Self {
match self % rhs {
0 => self,
r => self + (rhs - r),
}
}
#[inline]
fn msrv_checked_next_multiple_of(self, rhs: Self) -> Option<Self> {
{
match self.checked_rem(rhs)? {
0 => Some(self),
r => self.checked_add(rhs - r),
}
}
}
}
pub(crate) use crate::col::{Col, ColMut, ColRef};
pub(crate) use crate::diag::{Diag, DiagMut, DiagRef};
pub(crate) use crate::hacks::transmute;
pub(crate) use crate::linalg::{
self, temp_mat_scratch, temp_mat_uninit, temp_mat_zeroed,
};
pub(crate) use crate::mat::{
AsMat, AsMatMut, AsMatRef, Mat, MatMut, MatRef,
};
pub(crate) use crate::perm::{Perm, PermRef};
pub(crate) use crate::prelude::*;
pub(crate) use crate::row::{AsRowMut, AsRowRef, Row, RowMut, RowRef};
pub(crate) use crate::utils::bound::{Array, Dim, Idx, IdxInc, MaybeIdx};
pub(crate) use crate::utils::simd::SimdCtx;
pub(crate) use crate::{Auto, NonExhaustive, Side, Spec};
pub use faer_traits::ext::*;
pub use faer_traits::math_utils::*;
pub use faer_traits::{
ComplexField, ComplexImpl, ComplexImplConj, Conjugate, Index,
IndexCore, Real, RealField, SignedIndex, SimdArch, Symbolic,
};
pub use num_complex::Complex;
#[cfg(test)]
pub(crate) use std::dbg;
#[cfg(test)]
pub(crate) use {alloc::boxed::Box, alloc::vec, alloc::vec::Vec};
#[inline]
pub fn simd_align(i: usize) -> usize {
i.wrapping_neg()
}
pub use crate::make_guard;
pub(crate) use crate::{
Accum, Conj, ContiguousBwd, ContiguousFwd, DiagStatus, Par, Shape,
Stride, Unbind, unzip, zip,
};
pub use dyn_stack::{MemStack, StackReq, alloc as alloca};
pub use equator::{
assert, assert as Assert, debug_assert, debug_assert as DebugAssert,
};
pub use reborrow::*;
pub use {unzip as uz, zip as z};
}
#[allow(unused_imports)]
pub(crate) mod internal_prelude_sp {
pub(crate) use crate::internal_prelude::*;
pub(crate) use crate::sparse::{
FaerError, NONE, Pair, SparseColMat, SparseColMatMut, SparseColMatRef,
SparseRowMat, SparseRowMatMut, SparseRowMatRef, SymbolicSparseColMat,
SymbolicSparseColMatRef, SymbolicSparseRowMat, SymbolicSparseRowMatRef,
Triplet, csc_numeric, csc_symbolic, csr_numeric, csr_symbolic,
linalg as linalg_sp, try_collect, try_zeroed, windows2,
};
pub(crate) use core::cell::Cell;
pub(crate) use core::iter;
pub(crate) use dyn_stack::MemBuffer;
}
pub mod prelude {
#[cfg(feature = "linalg")]
pub use super::linalg::solvers::{DenseSolve, Solve, SolveLstsq};
#[cfg(feature = "sparse")]
pub use super::prelude_sp::*;
pub use super::{Par, Scale, c32, c64, col, mat, row, unzip, zip};
pub use col::{Col, ColMut, ColRef};
pub use mat::{Mat, MatMut, MatRef};
pub use reborrow::{IntoConst, Reborrow, ReborrowMut};
pub use row::{Row, RowMut, RowRef};
#[inline]
pub fn default<T: Default>() -> T {
Default::default()
}
}
#[cfg(feature = "sparse")]
mod prelude_sp {
use crate::sparse;
pub use sparse::{
SparseColMat, SparseColMatMut, SparseColMatRef, SparseRowMat,
SparseRowMatMut, SparseRowMatRef,
};
}
#[derive(Copy, Clone, Debug)]
#[repr(transparent)]
pub struct Scale<T>(pub T);
impl<T> Scale<T> {
#[inline(always)]
pub fn from_ref(value: &T) -> &Self {
unsafe { &*(value as *const T as *const Self) }
}
#[inline(always)]
pub fn from_mut(value: &mut T) -> &mut Self {
unsafe { &mut *(value as *mut T as *mut Self) }
}
}
static GLOBAL_PARALLELISM: AtomicUsize = {
#[cfg(all(not(miri), feature = "rayon"))]
{
AtomicUsize::new(2)
}
#[cfg(not(all(not(miri), feature = "rayon")))]
{
AtomicUsize::new(1)
}
};
pub fn disable_global_parallelism() {
GLOBAL_PARALLELISM.store(0, core::sync::atomic::Ordering::Relaxed);
}
pub fn set_global_parallelism(par: Par) {
let value = match par {
Par::Seq => 1,
#[cfg(feature = "rayon")]
Par::Rayon(n) => n.get().saturating_add(2),
};
GLOBAL_PARALLELISM.store(value, core::sync::atomic::Ordering::Relaxed);
}
#[track_caller]
pub fn get_global_parallelism() -> Par {
let value = GLOBAL_PARALLELISM.load(core::sync::atomic::Ordering::Relaxed);
match value {
0 => panic!("Global parallelism is disabled."),
1 => Par::Seq,
#[cfg(feature = "rayon")]
n => Par::rayon(n - 2),
#[cfg(not(feature = "rayon"))]
_ => unreachable!(),
}
}
#[doc(hidden)]
pub mod hacks;
pub mod stats;
mod non_exhaustive {
#[doc(hidden)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(transparent)]
pub struct NonExhaustive(pub(crate) ());
}
pub(crate) use non_exhaustive::NonExhaustive;
pub trait Auto<T> {
fn auto() -> Self;
}
pub struct Spec<Config, T> {
pub config: Config,
__marker: core::marker::PhantomData<fn() -> T>,
}
impl<Config, T> core::ops::Deref for Spec<Config, T> {
type Target = Config;
#[inline]
fn deref(&self) -> &Self::Target {
&self.config
}
}
impl<Config, T> core::ops::DerefMut for Spec<Config, T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.config
}
}
impl<Config: Copy, T> Copy for Spec<Config, T> {}
impl<Config: Clone, T> Clone for Spec<Config, T> {
#[inline]
fn clone(&self) -> Self {
Self::new(self.config.clone())
}
}
impl<Config: core::fmt::Debug, T> core::fmt::Debug for Spec<Config, T> {
#[inline]
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.config.fmt(f)
}
}
impl<Config, T> Spec<Config, T> {
#[inline]
pub fn new(config: Config) -> Self {
Spec {
config,
__marker: core::marker::PhantomData,
}
}
}
impl<T, Config> From<Config> for Spec<Config, T> {
#[inline]
fn from(config: Config) -> Self {
Spec {
config,
__marker: core::marker::PhantomData,
}
}
}
impl<T, Config: Auto<T>> Default for Spec<Config, T> {
#[inline]
fn default() -> Self {
Spec {
config: Auto::<T>::auto(),
__marker: core::marker::PhantomData,
}
}
}
mod into_range {
use super::*;
pub trait IntoRange<I> {
type Len<N: Shape>: Shape;
fn into_range(self, min: I, max: I) -> core::ops::Range<I>;
}
impl<I> IntoRange<I> for core::ops::Range<I> {
type Len<N: Shape> = usize;
#[inline]
fn into_range(self, _: I, _: I) -> core::ops::Range<I> {
self
}
}
impl<I> IntoRange<I> for core::ops::RangeFrom<I> {
type Len<N: Shape> = usize;
#[inline]
fn into_range(self, _: I, max: I) -> core::ops::Range<I> {
self.start..max
}
}
impl<I> IntoRange<I> for core::ops::RangeTo<I> {
type Len<N: Shape> = usize;
#[inline]
fn into_range(self, min: I, _: I) -> core::ops::Range<I> {
min..self.end
}
}
impl<I> IntoRange<I> for core::ops::RangeFull {
type Len<N: Shape> = N;
#[inline]
fn into_range(self, min: I, max: I) -> core::ops::Range<I> {
min..max
}
}
}
mod sort;
pub extern crate dyn_stack;
pub extern crate faer_traits as traits;
#[doc(hidden)]
pub extern crate generativity;
pub extern crate num_complex as complex;
#[cfg(feature = "rand")]
#[cfg_attr(docs_rs, doc(cfg(feature = "rand")))]
pub extern crate rand;
pub extern crate reborrow;
extern crate self as faer;
#[macro_export]
#[doc(hidden)]
macro_rules! simd_iter {
(for ($batch_id:tt, $i:pat $(,)?) in [$indices:expr; $batch_size:expr] $b:block $(,)?) => {#[allow(non_upper_case_globals, unconditional_panic)] 'out:{
let (__head__, __body_batch__, __body_item__, __tail__) = &$indices;
let __body_batch__ = __body_batch__.clone();
let mut __body_item__ = __body_item__.clone();
const {
::core::assert!($batch_size > 0);
::core::assert!($batch_size <= 8);
}
{
if const { $batch_size == 1 } {if $batch_size == 1 { const $batch_id: usize = 0; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 2 } {if $batch_size == 2 { const $batch_id: usize = 1; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 3 } {if $batch_size == 3 { const $batch_id: usize = 2; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 4 } {if $batch_size == 4 { const $batch_id: usize = 3; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 5 } {if $batch_size == 5 { const $batch_id: usize = 4; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 6 } {if $batch_size == 6 { const $batch_id: usize = 5; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 7 } {if $batch_size == 7 { const $batch_id: usize = 6; if let &Some($i) = __head__ $b; }}
if const { $batch_size == 8 } {if $batch_size == 8 { const $batch_id: usize = 7; if let &Some($i) = __head__ $b; }}
}
for __i__ in __body_batch__ {
let __i__: [_; $batch_size] = __i__;
let __i__ = __i__.as_slice();
::core::assert!(__i__.len() == $batch_size);
{
if const { $batch_size > 0 } {if __i__.len() > 0 { const $batch_id: usize = 0; let $i = __i__[0]; $b }}
if const { $batch_size > 1 } {if __i__.len() > 1 { const $batch_id: usize = 1; let $i = __i__[1]; $b }}
if const { $batch_size > 2 } {if __i__.len() > 2 { const $batch_id: usize = 2; let $i = __i__[2]; $b }}
if const { $batch_size > 3 } {if __i__.len() > 3 { const $batch_id: usize = 3; let $i = __i__[3]; $b }}
if const { $batch_size > 4 } {if __i__.len() > 4 { const $batch_id: usize = 4; let $i = __i__[4]; $b }}
if const { $batch_size > 5 } {if __i__.len() > 5 { const $batch_id: usize = 5; let $i = __i__[5]; $b }}
if const { $batch_size > 6 } {if __i__.len() > 6 { const $batch_id: usize = 6; let $i = __i__[6]; $b }}
if const { $batch_size > 7 } {if __i__.len() > 7 { const $batch_id: usize = 7; let $i = __i__[7]; $b }}
}
};
{
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; } } }
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; } } }
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; } } }
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; } } }
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; } } }
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; } } }
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; } } }
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; } } }
}
}};
(for $i:pat in [$indices:expr] $b:block $(,)?) => {#[allow(non_upper_case_globals)]{
let (__head__, __body__, __tail__) = &$indices;
if let &Some($i) = __head__ $b;
for $i in __body__.clone() $b;
if let &Some($i) = __tail__ $b;
}};
}