impl<F: SemiflowFloat> Float for Dual<F> {
#[inline]
fn nan() -> Self {
Self::constant(F::nan())
}
#[inline]
fn infinity() -> Self {
Self::constant(F::infinity())
}
#[inline]
fn neg_infinity() -> Self {
Self::constant(F::neg_infinity())
}
#[inline]
fn neg_zero() -> Self {
Self::constant(F::neg_zero())
}
#[inline]
fn min_value() -> Self {
Self::constant(F::min_value())
}
#[inline]
fn min_positive_value() -> Self {
Self::constant(F::min_positive_value())
}
#[inline]
fn epsilon() -> Self {
Self::constant(F::epsilon())
}
#[inline]
fn max_value() -> Self {
Self::constant(F::max_value())
}
#[inline]
fn is_nan(self) -> bool {
self.value.is_nan()
}
#[inline]
fn is_infinite(self) -> bool {
self.value.is_infinite()
}
#[inline]
fn is_finite(self) -> bool {
self.value.is_finite()
}
#[inline]
fn is_normal(self) -> bool {
self.value.is_normal()
}
#[inline]
fn is_subnormal(self) -> bool {
self.value.is_subnormal()
}
#[inline]
fn is_sign_positive(self) -> bool {
self.value.is_sign_positive()
}
#[inline]
fn is_sign_negative(self) -> bool {
self.value.is_sign_negative()
}
#[inline]
fn classify(self) -> core::num::FpCategory {
self.value.classify()
}
#[inline]
fn floor(self) -> Self {
Self::constant(self.value.floor())
}
#[inline]
fn ceil(self) -> Self {
Self::constant(self.value.ceil())
}
#[inline]
fn round(self) -> Self {
Self::constant(self.value.round())
}
#[inline]
fn trunc(self) -> Self {
Self::constant(self.value.trunc())
}
#[inline]
fn fract(self) -> Self {
Self::constant(self.value.fract())
}
#[inline]
fn signum(self) -> Self {
Self::constant(self.value.signum())
}
#[inline]
fn abs(self) -> Self {
Self::new(self.value.abs(), self.value.signum() * self.tangent)
}
#[inline]
fn min(self, o: Self) -> Self {
if self.value <= o.value {
self
} else {
o
}
}
#[inline]
fn max(self, o: Self) -> Self {
if self.value >= o.value {
self
} else {
o
}
}
#[inline]
fn clamp(self, lo: Self, hi: Self) -> Self {
if self.value < lo.value {
lo
} else if self.value > hi.value {
hi
} else {
self
}
}
#[inline]
fn recip(self) -> Self {
Self::new(
self.value.recip(),
-self.tangent / (self.value * self.value),
)
}
#[inline]
fn powi(self, n: i32) -> Self {
Self::new(
self.value.libm_powi(n),
F::from(n).unwrap_or_else(F::zero) * self.value.libm_powi(n - 1) * self.tangent,
)
}
#[inline]
fn powf(self, p: Self) -> Self {
let v = self.value.libm_powf(p.value);
Self::new(
v,
p.value * self.value.libm_powf(p.value - F::one()) * self.tangent,
)
}
#[inline]
fn sqrt(self) -> Self {
let v = self.value.sqrt();
Self::new(v, self.tangent / (v + v))
}
#[inline]
fn exp(self) -> Self {
let v = self.value.libm_exp();
Self::new(v, v * self.tangent)
}
#[inline]
fn exp2(self) -> Self {
let v = self.value.libm_exp2();
let ln2 = F::from(2.0_f64.libm_ln()).unwrap_or_else(F::zero);
Self::new(v, v * ln2 * self.tangent)
}
#[inline]
fn ln(self) -> Self {
Self::new(self.value.libm_ln(), self.tangent / self.value)
}
#[inline]
fn log(self, base: Self) -> Self {
self.libm_ln() / base.libm_ln()
}
#[inline]
fn log2(self) -> Self {
let ln2 = F::from(2.0_f64.libm_ln()).unwrap_or_else(F::zero);
Self::new(self.value.libm_log2(), self.tangent / (self.value * ln2))
}
#[inline]
fn log10(self) -> Self {
let ln10 = F::from(10.0_f64.libm_ln()).unwrap_or_else(F::zero);
Self::new(self.value.libm_log10(), self.tangent / (self.value * ln10))
}
#[allow(deprecated)]
#[inline]
fn abs_sub(self, o: Self) -> Self {
Self::constant(self.value.abs_sub(o.value))
}
#[inline]
fn cbrt(self) -> Self {
let v = self.value.libm_cbrt();
let three = F::from(3.0_f64).unwrap_or_else(F::one);
Self::new(v, self.tangent / (three * v * v))
}
#[inline]
fn hypot(self, o: Self) -> Self {
let v = self.value.libm_hypot(o.value);
Self::new(v, (self.value * self.tangent + o.value * o.tangent) / v)
}
#[inline]
fn sin(self) -> Self {
Self::new(self.value.libm_sin(), self.value.libm_cos() * self.tangent)
}
#[inline]
fn cos(self) -> Self {
Self::new(self.value.libm_cos(), -self.value.libm_sin() * self.tangent)
}
#[inline]
fn tan(self) -> Self {
let c = self.value.libm_cos();
Self::new(self.value.libm_tan(), self.tangent / (c * c))
}
#[inline]
fn asin(self) -> Self {
Self::new(
self.value.libm_asin(),
self.tangent / (F::one() - self.value * self.value).sqrt(),
)
}
#[inline]
fn acos(self) -> Self {
Self::new(
self.value.libm_acos(),
-self.tangent / (F::one() - self.value * self.value).sqrt(),
)
}
#[inline]
fn atan(self) -> Self {
Self::new(
self.value.libm_atan(),
self.tangent / (F::one() + self.value * self.value),
)
}
#[inline]
fn atan2(self, o: Self) -> Self {
let d = self.value * self.value + o.value * o.value;
Self::new(
self.value.libm_atan2(o.value),
(o.value * self.tangent - self.value * o.tangent) / d,
)
}
#[inline]
fn sin_cos(self) -> (Self, Self) {
(self.libm_sin(), self.libm_cos())
}
#[inline]
fn exp_m1(self) -> Self {
Self::new(self.value.libm_exp_m1(), self.value.libm_exp() * self.tangent)
}
#[inline]
fn ln_1p(self) -> Self {
Self::new(self.value.libm_ln_1p(), self.tangent / (F::one() + self.value))
}
#[inline]
fn sinh(self) -> Self {
Self::new(self.value.libm_sinh(), self.value.libm_cosh() * self.tangent)
}
#[inline]
fn cosh(self) -> Self {
Self::new(self.value.libm_cosh(), self.value.libm_sinh() * self.tangent)
}
#[inline]
fn tanh(self) -> Self {
let v = self.value.libm_tanh();
Self::new(v, (F::one() - v * v) * self.tangent)
}
#[inline]
fn asinh(self) -> Self {
Self::new(
self.value.libm_asinh(),
self.tangent / (self.value * self.value + F::one()).sqrt(),
)
}
#[inline]
fn acosh(self) -> Self {
Self::new(
self.value.libm_acosh(),
self.tangent / (self.value * self.value - F::one()).sqrt(),
)
}
#[inline]
fn atanh(self) -> Self {
Self::new(
self.value.libm_atanh(),
self.tangent / (F::one() - self.value * self.value),
)
}
#[inline]
fn to_degrees(self) -> Self {
let k = F::from(180.0_f64 / core::f64::consts::PI).unwrap_or_else(F::one);
Self::new(self.value.to_degrees(), self.tangent * k)
}
#[inline]
fn to_radians(self) -> Self {
let k = F::from(core::f64::consts::PI / 180.0_f64).unwrap_or_else(F::one);
Self::new(self.value.to_radians(), self.tangent * k)
}
#[inline]
fn integer_decode(self) -> (u64, i16, i8) {
self.value.integer_decode()
}
#[inline]
fn mul_add(self, a: Self, b: Self) -> Self {
Self::new(
self.value.mul_add(a.value, b.value),
self.tangent * a.value + self.value * a.tangent + b.tangent,
)
}
#[inline]
fn copysign(self, sign: Self) -> Self {
Self::new(
self.value.copysign(sign.value),
self.tangent.copysign(sign.value),
)
}
}