// codesnip-guard: DualNumber #[cfg_attr(any(),rustfmt::skip)]pub use self::dual_number::DualNumber;#[cfg_attr(any(),rustfmt::skip)]mod dual_number{use super::{One,Zero};use std::{iter::{Product,Sum},ops::{Add,AddAssign,Div,DivAssign,Mul,MulAssign,Neg,Sub,SubAssign}};#[derive(Clone,Copy,Debug,Default,PartialEq,Eq,PartialOrd,Ord,Hash)]pub struct DualNumber(pub T,pub T);implDualNumber{pub fn transpose(self)->Self{Self(self.1,self.0)}}implZero for DualNumberwhere T:Zero{fn zero()->Self{Self(T::zero(),T::zero())}}implOne for DualNumberwhere T:Zero+One{fn one()->Self{Self(T::one(),T::zero())}}implDualNumberwhere T:Zero+One{pub fn epsilon()->Self{Self(T::zero(),T::one())}}implDualNumberwhere T:Neg{pub fn conjugate(self)->Self{Self(self.0,-self.1)}}implDualNumberwhere T:Add+Mul{pub fn eval(self,eps:T)->T{self.0+self.1*eps}}implDualNumberwhere T:Div+Neg{pub fn root(self)->T{-self.0/self.1}}implAdd for DualNumberwhere T:Add{type Output=Self;fn add(self,rhs:Self)->Self::Output{Self(self.0+rhs.0,self.1+rhs.1)}}implAddfor DualNumberwhere T:Add{type Output=Self;fn add(self,rhs:T)->Self::Output{Self(self.0+rhs,self.1)}}implSub for DualNumberwhere T:Sub{type Output=Self;fn sub(self,rhs:Self)->Self::Output{Self(self.0-rhs.0,self.1-rhs.1)}}implSubfor DualNumberwhere T:Sub{type Output=Self;fn sub(self,rhs:T)->Self::Output{Self(self.0-rhs,self.1)}}implMul for DualNumberwhere T:Clone+Add+Sub+Mul{type Output=Self;fn mul(self,rhs:Self)->Self::Output{Self(self.0 .clone()*rhs.0 .clone(),self.0*rhs.1+self.1*rhs.0)}}implMulfor DualNumberwhere T:Clone+Mul{type Output=Self;fn mul(self,rhs:T)->Self::Output{Self(self.0*rhs.clone(),self.1*rhs)}}implDiv for DualNumberwhere T:Clone+One+Add+Sub+Mul+Div{type Output=Self;fn div(self,rhs:Self)->Self::Output{let d=T::one()/rhs.1 .clone();Self(self.0 .clone()*d.clone(),(self.1*rhs.0-self.0*rhs.1)*d.clone()*d)}}implDivfor DualNumberwhere T:Clone+One+Div{type Output=Self;fn div(self,rhs:T)->Self::Output{let d=T::one()/rhs.clone();Self(self.0/d.clone(),self.1/d)}}implNeg for DualNumberwhere T:Neg{type Output=Self;fn neg(self)->Self::Output{Self(-self.0,-self.1)}}macro_rules!impl_dual_number_ref_binop{(impl<$T:ident>$imp:ident$method:ident($l:ty,$r:ty)where$($w:ident)*$(+$($v:ident)*)?)=>{impl<$T>$imp<$r>for&$l where$T:Clone$(+$w)*$($(+$v)*)?,{type Output=<$l as$imp<$r>>::Output;fn$method(self,rhs:$r)-><$l as$imp<$r>>::Output{$imp::$method(self.clone(),rhs)}}impl<$T>$imp<&$r>for$l where$T:Clone$(+$w)*$($(+$v)*)?,{type Output=<$l as$imp<$r>>::Output;fn$method(self,rhs:&$r)-><$l as$imp<$r>>::Output{$imp::$method(self,rhs.clone())}}impl<$T>$imp<&$r>for&$l where$T:Clone$(+$w)*$($(+$v)*)?,{type Output=<$l as$imp<$r>>::Output;fn$method(self,rhs:&$r)-><$l as$imp<$r>>::Output{$imp::$method(self.clone(),rhs.clone())}}};}impl_dual_number_ref_binop!(implAdd add(DualNumber,DualNumber)where Add);impl_dual_number_ref_binop!(implAdd add(DualNumber,T)where Add);impl_dual_number_ref_binop!(implSub sub(DualNumber,DualNumber)where Sub);impl_dual_number_ref_binop!(implSub sub(DualNumber,T)where Sub);impl_dual_number_ref_binop!(implMul mul(DualNumber,DualNumber)where Add Sub Mul);impl_dual_number_ref_binop!(implMul mul(DualNumber,T)where Mul);impl_dual_number_ref_binop!(implDiv div(DualNumber,DualNumber)where Add Sub Mul Div+One);impl_dual_number_ref_binop!(implDiv div(DualNumber,T)where Div+One);macro_rules!impl_dual_number_ref_unop{(impl<$T:ident>$imp:ident$method:ident($t:ty)where$($w:ident)*)=>{impl<$T>$imp for&$t where$T:Clone$(+$w)*,{type Output=<$t as$imp>::Output;fn$method(self)-><$t as$imp>::Output{$imp::$method(self.clone())}}};}impl_dual_number_ref_unop!(implNeg neg(DualNumber)where Neg);macro_rules!impl_dual_number_op_assign{(impl<$T:ident>$imp:ident$method:ident($l:ty,$r:ty)$fromimp:ident$frommethod:ident where$($w:ident)*$(+$($v:ident)*)?)=>{impl<$T>$imp<$r>for$l where$T:Clone$(+$w)*$($(+$v)*)?,{fn$method(&mut self,rhs:$r){*self=$fromimp::$frommethod(self.clone(),rhs);}}impl<$T>$imp<&$r>for$l where$T:Clone$(+$w)*$($(+$v)*)?,{fn$method(&mut self,rhs:&$r){$imp::$method(self,rhs.clone());}}};}impl_dual_number_op_assign!(implAddAssign add_assign(DualNumber,DualNumber)Add add where Add);impl_dual_number_op_assign!(implAddAssign add_assign(DualNumber,T)Add add where Add);impl_dual_number_op_assign!(implSubAssign sub_assign(DualNumber,DualNumber)Sub sub where Sub);impl_dual_number_op_assign!(implSubAssign sub_assign(DualNumber,T)Sub sub where Sub);impl_dual_number_op_assign!(implMulAssign mul_assign(DualNumber,DualNumber)Mul mul where Add Sub Mul);impl_dual_number_op_assign!(implMulAssign mul_assign(DualNumber,T)Mul mul where Mul);impl_dual_number_op_assign!(implDivAssign div_assign(DualNumber,DualNumber)Div div where Add Sub Mul Div+One);impl_dual_number_op_assign!(implDivAssign div_assign(DualNumber,T)Div div where Div+One);macro_rules!impl_dual_number_fold{(impl<$T:ident>$imp:ident$method:ident($t:ty)$identimp:ident$identmethod:ident$fromimp:ident$frommethod:ident where$($w:ident)*$(+$x:ident)*)=>{impl<$T>$imp for$t where$T:$identimp$(+$w)*$(+$x)*,{fn$method>(iter:I)->Self{iter.fold(::$identmethod(),$fromimp::$frommethod)}}impl<'a,$T:'a>$imp<&'a$t>for$t where$T:Clone+$identimp$(+$w)*$(+$x)*,{fn$method>(iter:I)->Self{iter.fold(::$identmethod(),$fromimp::$frommethod)}}};}impl_dual_number_fold!(implSum sum(DualNumber)Zero zero Add add where Add);impl_dual_number_fold!(implProduct product(DualNumber)One one Mul mul where Add Sub Mul+Zero+Clone);} // codesnip-guard: zero_one #[cfg_attr(any(),rustfmt::skip)]pub use self::zero_one::{One,Zero};#[cfg_attr(any(),rustfmt::skip)]mod zero_one{pub trait Zero:Sized{fn zero()->Self;#[inline]fn is_zero(&self)->bool where Self:PartialEq{self==&Self::zero()}#[inline]fn set_zero(&mut self){*self=Self::zero();}}pub trait One:Sized{fn one()->Self;#[inline]fn is_one(&self)->bool where Self:PartialEq{self==&Self::one()}#[inline]fn set_one(&mut self){*self=Self::one();}}macro_rules!impl_zero_one{($({$(<$T:ident:$Bound:ident>)?$Trait:ident$method:ident$($t:ty)*,$e:expr})*)=>{$(impl_zero_one!(@impl[$(<$T:$Bound>)?]$Trait$method[$($t)*],$e);)*};(@impl[<$T:ident:$Bound:ident>]$Trait:ident$method:ident[$($t:ty)*],$e:expr)=>{$(impl<$T:$Bound>$Trait for$t{fn$method()->Self{$e}})*};(@impl[]$Trait:ident$method:ident[$($t:ty)*],$e:expr)=>{$(impl$Trait for$t{fn$method()->Self{$e}})*};}impl_zero_one!({Zero zero u8 u16 u32 u64 usize i8 i16 i32 i64 isize u128 i128,0}{Zero zero f32 f64,0.}{One one u8 u16 u32 u64 usize i8 i16 i32 i64 isize u128 i128,1}{One one f32 f64,1.}{Zero zero std::num::Wrapping,Self(T::zero())}{One one std::num::Wrapping,Self(T::one())});}