num_dual/datatypes/
real.rs

1use crate::{DualNum, DualNumFloat, DualStruct};
2use num_traits::{Float, FloatConst, FromPrimitive, Inv, Num, One, Signed, Zero};
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5use std::fmt;
6use std::iter::{Product, Sum};
7use std::marker::PhantomData;
8use std::ops::{
9    Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign,
10};
11
12/// A real number for the calculations of zeroth derivatives in generic contexts.
13///
14/// In most situations f64 or f32 can be used directly!
15#[derive(Copy, Clone, Debug, PartialEq)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub struct Real<T: DualNum<F>, F> {
18    /// Real part of the dual number
19    pub re: T,
20    #[cfg_attr(feature = "serde", serde(skip))]
21    f: PhantomData<F>,
22}
23
24#[cfg(feature = "ndarray")]
25impl<T: DualNum<F>, F: DualNumFloat> ndarray::ScalarOperand for Real<T, F> {}
26
27impl<T: DualNum<F>, F> Real<T, F> {
28    /// Create a new dual number from its fields.
29    #[inline]
30    pub fn new(re: T) -> Self {
31        Self { re, f: PhantomData }
32    }
33}
34
35impl<T: DualNum<F> + Zero, F> Real<T, F> {
36    /// Create a new dual number from the real part.
37    #[inline]
38    pub fn from_re(re: T) -> Self {
39        Self::new(re)
40    }
41}
42
43/* chain rule */
44impl<T: DualNum<F>, F: Float> Real<T, F> {
45    #[inline]
46    fn chain_rule(&self, f0: T) -> Self {
47        Self::new(f0)
48    }
49}
50
51/* product rule */
52impl<T: DualNum<F>, F: Float> Mul<&Real<T, F>> for &Real<T, F> {
53    type Output = Real<T, F>;
54    #[inline]
55    fn mul(self, other: &Real<T, F>) -> Self::Output {
56        Real::new(self.re.clone() * other.re.clone())
57    }
58}
59
60/* quotient rule */
61impl<T: DualNum<F>, F: Float> Div<&Real<T, F>> for &Real<T, F> {
62    type Output = Real<T, F>;
63    #[inline]
64    #[expect(clippy::suspicious_arithmetic_impl)]
65    fn div(self, other: &Real<T, F>) -> Real<T, F> {
66        let inv = other.re.recip();
67        Real::new(self.re.clone() * inv.clone())
68    }
69}
70
71/* string conversions */
72impl<T: DualNum<F>, F> fmt::Display for Real<T, F> {
73    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
74        fmt::Display::fmt(&self.re, f)
75    }
76}
77
78impl_zeroth_derivatives!(Real, []);
79impl_dual!(Real, []);