#![cfg_attr(not(feature = "std"), no_std)]
#![allow(non_snake_case)]
#![warn(missing_docs)]
#![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 { extern crate generativity; ::generativity::Id::new() };
#[allow(unused, unused_unsafe)]
let lifetime_brand = unsafe { extern crate generativity; ::generativity::LifetimeBrand::new(&$name) };
#[allow(unused_unsafe)]
let $name = unsafe { extern crate generativity; ::generativity::Guard::new($name) };
)*};
}
macro_rules! repeat_n {
($e: expr, $n: expr) => {
iter::repeat_n($e, $n)
};
}
macro_rules! try_const {
($e: expr) => {
::pulp::try_const! { $e }
};
}
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 try_const! { <$T>::IS_NATIVE_C32 } {
unsafe { transmute(<ComplexImpl<f32> as ComplexField>::Arch::default().dispatch(transmute::<_, $ty<ComplexImpl<f32>>>($imp))) }
} else if try_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 = $name.as_mat_mut();
};
($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: ty),* $(,)?) => {
$crate::linalg::zip::Zip::<$head, $crate::Zip!($($tail,)*)>
};
}
#[macro_export]
macro_rules! unzip {
($head: pat $(,)?) => {
$crate::linalg::zip::Last($head)
};
($head: pat, $($tail: pat),* $(,)?) => {
$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())
}
}
};
}
#[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())
}
}
};
}
#[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())
}
}
};
}
#[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 utils;
pub mod diag;
pub mod mat;
pub mod perm;
pub mod col;
pub mod row;
pub mod linalg;
#[path = "./operator/mod.rs"]
pub mod matrix_free;
pub mod sparse;
#[cfg(feature = "std")]
pub mod io;
#[cfg(feature = "serde")]
mod serde;
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 try_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 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),
}
}
}
}
#[cfg(test)]
pub(crate) use std::dbg;
#[cfg(test)]
pub(crate) use {alloc::boxed::Box, alloc::vec, alloc::vec::Vec};
pub use faer_traits::{ComplexImpl, ComplexImplConj, Symbolic};
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 num_complex::Complex;
pub use faer_macros::math;
pub use faer_traits::math_utils::*;
pub use faer_traits::{ComplexField, Conjugate, Index, IndexCore, Real, RealField, SignedIndex, SimdArch};
#[inline]
pub fn simd_align(i: usize) -> usize {
i.wrapping_neg()
}
pub(crate) use crate::{Accum, Conj, ContiguousBwd, ContiguousFwd, DiagStatus, Par, Shape, Stride, Unbind, unzip, zip};
pub use {unzip as uz, zip as z};
pub use crate::make_guard;
pub use dyn_stack::{MemStack, StackReq};
pub use equator::{assert, assert as Assert, debug_assert, debug_assert as DebugAssert};
pub use reborrow::*;
}
#[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 {
pub use reborrow::{IntoConst, Reborrow, ReborrowMut};
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 row::{Row, RowMut, RowRef};
#[cfg(feature = "linalg")]
pub use super::linalg::solvers::{DenseSolve, Solve, SolveLstsq};
#[cfg(feature = "sparse")]
pub use super::prelude_sp::*;
#[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;
pub extern crate num_complex as complex;
pub extern crate reborrow;
#[cfg(feature = "rand")]
#[cfg_attr(docs_rs, doc(cfg(feature = "rand")))]
pub extern crate rand;