Skip to content

Commit

Permalink
add Float and ExtFloat methods for calculus
Browse files Browse the repository at this point in the history
- add `derivative`, `integrate`, `partial_derivative_x`, `partial_derivative_y`.
  • Loading branch information
joseluis committed Nov 29, 2024
1 parent c115aa4 commit 78c6119
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 1 deletion.
4 changes: 3 additions & 1 deletion DOCS/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ The format is based on [Keep a Changelog], and this project adheres to
- `Array` when storing `Option<T>`.
- `BareBox`.
- `ExtAny` method `type_id`.
- `Float` and `ExtFloat` method `eval_poly` to evaluate polynomials.
- `Float` and `ExtFloat`:
- `eval_poly` to evaluate polynomials.
- for calculus: `derivative`, `integrate`, `partial_derivative_[x|y]`.
- `Float` and `ExtFloatConst` consts: `LOW_MARGIN`, `MEDIUM_MARGIN`, `HIGH_MARGIN`.
- `Graph` methods: `edge_exists_unchecked`, `edge_remove`.
- `NonValue*`: `is_max`, `is_min`, `[checked|strict|saturating|wrapping]_[add|sub]`.
Expand Down
54 changes: 54 additions & 0 deletions src/num/float/ext_float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,37 @@ pub trait ExtFloat: ExtFloatConst + Sized {
/// [Horner's method]: https://en.wikipedia.org/wiki/Horner%27s_method#Polynomial_evaluation_and_long_division
#[must_use]
fn eval_poly(self, coefficients: &[Self]) -> Self;

/// Approximates the derivative of the 1D function `f` at `x` point using step size `h`.
///
/// Uses the [finite difference method].
///
/// See also the [`autodiff`] attr macro, enabled with the `nightly_autodiff` feature.
///
/// [finite difference method]: https://en.wikipedia.org/wiki/Finite_difference_method
fn derivative<F>(f: F, x: Self, h: Self) -> Self
where
F: Fn(Self) -> Self;

/// Approximates the integral of the 1D function `f` over the range `[x, y]`
/// using `n` subdivisions.
///
/// Uses the [Riemann Sum](https://en.wikipedia.org/wiki/Riemann_sum).
fn integrate<F>(f: F, x: Self, y: Self, n: usize) -> Self
where
F: Fn(Self) -> Self;

/// Approximates the partial derivative of the 2D function `f` at point (`x`, `y`)
/// with step size `h`, differentiating over `x`.
fn partial_derivative_x<F>(f: F, x: Self, y: Self, h: Self) -> Self
where
F: Fn(Self, Self) -> Self;

/// Approximates the partial derivative of the 2D function `f` at point (`x`, `y`)
/// with step size `h`, differentiating over `x`.
fn partial_derivative_y<F>(f: F, x: Self, y: Self, h: Self) -> Self
where
F: Fn(Self, Self) -> Self;
}

#[doc = crate::doc_private!()]
Expand Down Expand Up @@ -711,6 +742,29 @@ macro_rules! impl_float_ext {
fn eval_poly(self, coefficients: &[Self]) -> Self {
Float(self).eval_poly(coefficients).0
}

fn derivative<F>(f: F, x: Self, h: Self) -> Self
where F: Fn(Self) -> Self {
Float::<Self>::derivative(f, x, h).0
}
fn integrate<F>(f: F, x: Self, y: Self, n: usize) -> Self
where F: Fn(Self) -> Self {
Float::<Self>::integrate(f, x, y, n).0
}

fn partial_derivative_x<F>(f: F, x: Self, y: Self, h: Self) -> Self
where
F: Fn(Self, Self) -> Self,
{
Float::<Self>::partial_derivative_x(f, x, y, h).0
}

fn partial_derivative_y<F>(f: F, x: Self, y: Self, h: Self) -> Self
where
F: Fn(Self, Self) -> Self,
{
Float::<Self>::partial_derivative_y(f, x, y, h).0
}
}
}
}
Expand Down
70 changes: 70 additions & 0 deletions src/num/float/wrapper/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,76 @@ macro_rules! custom_impls {
}
}
}

/// Approximates the derivative of the 1D function `f` at `x` point using step size `h`.
///
/// Uses the [finite difference method].
///
/// # Formula
/// $$ f'(x) \approx \frac{f(x + h) - f(x)}{h} $$
///
/// See also the [`autodiff`] attr macro, enabled with the `nightly_autodiff` feature.
///
/// [finite difference method]: https://en.wikipedia.org/wiki/Finite_difference_method
pub fn derivative<F>(f: F, x: $f, h: $f) -> Float<$f>
where
F: Fn($f) -> $f,
{
Float((f(x + h) - f(x)) / h)
}

/// Approximates the integral of the 1D function `f` over the range `[x, y]`
/// using `n` subdivisions.
///
/// Uses the [Riemann Sum](https://en.wikipedia.org/wiki/Riemann_sum).
///
/// # Formula
/// $$
/// \int_a^b f(x) \, dx \approx \sum_{i=0}^{n-1} f(x_i) \cdot \Delta x
/// $$
/// where
/// $$
/// \Delta x = \frac{b-a}{n}
/// $$
pub fn integrate<F>(f: F, x: $f, y: $f, n: usize) -> Float<$f>
where
F: Fn($f) -> $f,
{
let dx = (y - x) / n as $f;
Float(
(0..n)
.map(|i| { let x = x + i as $f * dx; f(x) * dx })
.sum()
)
}

/// Approximates the partial derivative of the 2D function `f` at point (`x`, `y`)
/// with step size `h`, differentiating over `x`.
///
/// # Formula
/// $$
/// \frac{\partial f}{\partial x} \approx \frac{f(x + h, y) - f(x, y)}{h}
/// $$
pub fn partial_derivative_x<F>(f: F, x: $f, y: $f, h: $f) -> Float<$f>
where
F: Fn($f, $f) -> $f,
{
Float((f(x + h, y) - f(x, y)) / h)
}

/// Approximates the partial derivative of the 2D function `f` at point (`x`, `y`)
/// with step size `h`, differentiating over `x`.
///
/// # Formula
/// $$
/// \frac{\partial f}{\partial x} \approx \frac{f(x + h, y) - f(x, y)}{h}
/// $$
pub fn partial_derivative_y<F>(f: F, x: $f, y: $f, h: $f) -> Float<$f>
where
F: Fn($f, $f) -> $f,
{
Float((f(x, y + h) - f(x, y)) / h)
}
}
};
}
Expand Down

0 comments on commit 78c6119

Please sign in to comment.