-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Migrated the remaining parts of
math
module.
We now have `slice`, `rng` and `func` modules in the codebase. This commit does not include unit tests and documentation, whose progress can be tracked on issues #23 and #22 respectively. Added `lazy_static` as a dependency.
- Loading branch information
1 parent
f36ffc6
commit 9e02998
Showing
10 changed files
with
749 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
//! Formula implementation. | ||
|
||
use crate::math::is_ascending; | ||
use ndarray::Array1; | ||
use std::fmt::{Display, Error, Formatter}; | ||
|
||
/// Mathematical formulae accepting a single scalar argument. | ||
#[derive(Debug, Clone)] | ||
pub enum Formula { | ||
/// Constant value. = c | ||
Constant { | ||
/// Constant. | ||
c: f64, | ||
}, | ||
/// Line formula. = mx + c | ||
Line { | ||
/// Offset. | ||
c: f64, | ||
/// Gradient. | ||
m: f64, | ||
}, | ||
/// Bifurcation formula. = if x < t { under } else { over }. | ||
Bifurcation { | ||
/// Threshold value. | ||
t: f64, | ||
/// Under value. | ||
under: f64, | ||
/// Over value. | ||
over: f64, | ||
}, | ||
/// Constant value spline. | ||
ConstantSpline { | ||
/// X change points. | ||
xs: Array1<f64>, | ||
/// Y values. | ||
ys: Array1<f64>, | ||
}, | ||
/// Linear spline. | ||
LinearSpline { | ||
/// X change points. | ||
xs: Array1<f64>, | ||
/// Y values. | ||
ys: Array1<f64>, | ||
/// Gradient between points. | ||
grads: Array1<f64>, | ||
}, | ||
/// Quadratic spline. | ||
QuadraticSpline { | ||
/// X change points. | ||
xs: Array1<f64>, | ||
/// Y values. | ||
ys: Array1<f64>, | ||
/// Gradient between points. | ||
grads: Array1<f64>, | ||
/// Second order term between points. | ||
quads: Array1<f64>, | ||
}, | ||
} | ||
|
||
impl Formula { | ||
/// Construct a constant spline instance. | ||
#[inline] | ||
#[must_use] | ||
pub fn new_constant_spline(xs: Array1<f64>, ys: Array1<f64>) -> Self { | ||
debug_assert!(xs.len() >= 2); | ||
debug_assert!(is_ascending(xs.as_slice().unwrap())); | ||
debug_assert!(ys.len() == xs.len()); | ||
|
||
Self::ConstantSpline { xs, ys } | ||
} | ||
|
||
/// Construct a linear spline instance. | ||
#[inline] | ||
#[must_use] | ||
pub fn new_linear_spline(xs: Array1<f64>, ys: Array1<f64>, grads: Array1<f64>) -> Self { | ||
debug_assert!(xs.len() >= 2); | ||
debug_assert!(is_ascending(xs.as_slice().unwrap())); | ||
debug_assert!(ys.len() == xs.len()); | ||
debug_assert!((grads.len() + 1) == xs.len()); | ||
|
||
Self::LinearSpline { xs, ys, grads } | ||
} | ||
|
||
/// Construct a linear spline instance. | ||
#[inline] | ||
#[must_use] | ||
pub fn new_linear_spline_auto(xs: Array1<f64>, ys: Array1<f64>) -> Self { | ||
debug_assert!(xs.len() >= 2); | ||
debug_assert!(is_ascending(xs.as_slice().unwrap())); | ||
debug_assert!(ys.len() == xs.len()); | ||
|
||
let mut grads = Vec::with_capacity(xs.len() - 1); | ||
for ((x_curr, x_next), (y_curr, y_next)) in xs | ||
.iter() | ||
.zip(xs.iter().skip(1)) | ||
.zip(ys.iter().zip(ys.iter().skip(1))) | ||
{ | ||
grads.push((y_next - y_curr) / (x_next - x_curr)); | ||
} | ||
|
||
Self::new_linear_spline(xs, ys, Array1::from(grads)) | ||
} | ||
|
||
/// Construct a quadratic spline instance. | ||
#[inline] | ||
#[must_use] | ||
pub fn new_quadratic_spline( | ||
xs: Array1<f64>, | ||
ys: Array1<f64>, | ||
grads: Array1<f64>, | ||
quads: Array1<f64>, | ||
) -> Self { | ||
debug_assert!(xs.len() >= 2); | ||
debug_assert!(is_ascending(xs.as_slice().unwrap())); | ||
debug_assert!(ys.len() == xs.len()); | ||
debug_assert!((grads.len() + 1) == xs.len()); | ||
debug_assert!((quads.len() + 1) == xs.len()); | ||
|
||
Self::QuadraticSpline { | ||
xs, | ||
ys, | ||
grads, | ||
quads, | ||
} | ||
} | ||
|
||
/// Determine the corresponding output value for the given input. | ||
#[inline] | ||
#[must_use] | ||
pub fn y(&self, x: f64) -> f64 { | ||
match *self { | ||
Self::Constant { ref c } => *c, | ||
Self::Line { c, m } => x.mul_add(m, c), | ||
Self::Bifurcation { | ||
ref t, | ||
ref under, | ||
ref over, | ||
} => { | ||
if x < *t { | ||
*under | ||
} else { | ||
*over | ||
} | ||
} | ||
Self::ConstantSpline { ref xs, ref ys } => { | ||
debug_assert!(x >= xs[0]); | ||
debug_assert!(x <= xs[xs.len() - 1]); | ||
|
||
for (index, xn) in xs.iter().enumerate() { | ||
if *xn > x { | ||
return ys[index - 1]; | ||
} | ||
} | ||
ys[ys.len() - 1] | ||
} | ||
Self::LinearSpline { | ||
ref xs, | ||
ref ys, | ||
ref grads, | ||
} => { | ||
debug_assert!(x >= xs[0]); | ||
debug_assert!(x <= xs[xs.len() - 1]); | ||
|
||
for (index, xn) in xs.iter().enumerate() { | ||
if *xn > x { | ||
let dx = x - xs[index - 1]; | ||
return grads[index - 1].mul_add(dx, ys[index - 1]); | ||
} | ||
} | ||
ys[ys.len() - 1] | ||
} | ||
Self::QuadraticSpline { | ||
ref xs, | ||
ref ys, | ||
ref grads, | ||
ref quads, | ||
} => { | ||
debug_assert!(x >= xs[0]); | ||
debug_assert!(x <= xs[xs.len() - 1]); | ||
|
||
for (index, xn) in xs.iter().enumerate() { | ||
if *xn > x { | ||
let dx = x - xs[index - 1]; | ||
let y = ys[index - 1]; | ||
let g = grads[index - 1]; | ||
let q = quads[index - 1]; | ||
return q.mul_add(dx * dx, g.mul_add(dx, y)); | ||
} | ||
} | ||
ys[ys.len() - 1] | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl Display for Formula { | ||
#[inline] | ||
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> { | ||
let kind = match *self { | ||
Self::Constant { .. } => "Constant", | ||
Self::Line { .. } => "Line", | ||
Self::Bifurcation { .. } => "Bifurcation", | ||
Self::ConstantSpline { .. } => "Constant Spline", | ||
Self::LinearSpline { .. } => "Linear Spline", | ||
Self::QuadraticSpline { .. } => "Quadrati Spline", | ||
}; | ||
write!(fmt, "{}", kind) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
//! Formula form implementation. | ||
|
||
use crate::ord::Build; | ||
use arctk_attr::file; | ||
use ndarray::Array1; | ||
use std::fmt::{Display, Formatter}; | ||
|
||
/// Mathematical formulae accepting a single scalar argument. | ||
#[file] | ||
pub enum FormulaBuilder { | ||
/// Constant value. = c | ||
Constant(f64), | ||
/// Line formula. = (x * m) + c | ||
Line(f64, f64), | ||
/// Bifurcation formula. = x < y ? a : b. | ||
Bifurcation(f64, f64, f64), | ||
/// Constant value spline. | ||
ConstantSpline(Vec<f64>, Vec<f64>), | ||
/// Linear spline between points. | ||
LinearSpline(Vec<f64>, Vec<f64>, Vec<f64>), | ||
/// Connected linear spline between points. | ||
LinearSplineAuto(Vec<f64>, Vec<f64>), | ||
/// Quadratic spline between points. | ||
QuadraticSpline(Vec<f64>, Vec<f64>, Vec<f64>, Vec<f64>), | ||
} | ||
|
||
impl Build for FormulaBuilder { | ||
type Inst = crate::math::Formula; | ||
|
||
#[inline] | ||
fn build(self) -> Self::Inst { | ||
match self { | ||
Self::Constant(c) => Self::Inst::Constant { c }, | ||
Self::Line(c, m) => Self::Inst::Line { c, m }, | ||
Self::Bifurcation(t, under, over) => Self::Inst::Bifurcation { t, under, over }, | ||
Self::ConstantSpline(xs, ys) => { | ||
Self::Inst::new_constant_spline(Array1::from(xs), Array1::from(ys)) | ||
} | ||
Self::LinearSpline(xs, ys, grads) => Self::Inst::new_linear_spline( | ||
Array1::from(xs), | ||
Array1::from(ys), | ||
Array1::from(grads), | ||
), | ||
Self::LinearSplineAuto(xs, ys) => { | ||
Self::Inst::new_linear_spline_auto(Array1::from(xs), Array1::from(ys)) | ||
} | ||
Self::QuadraticSpline(xs, ys, grads, quads) => Self::Inst::new_quadratic_spline( | ||
Array1::from(xs), | ||
Array1::from(ys), | ||
Array1::from(grads), | ||
Array1::from(quads), | ||
), | ||
} | ||
} | ||
} | ||
|
||
impl Display for FormulaBuilder { | ||
#[inline] | ||
fn fmt(&self, fmt: &mut Formatter) -> std::fmt::Result { | ||
let kind = match *self { | ||
Self::Constant { .. } => "Constant", | ||
Self::Line { .. } => "Line", | ||
Self::Bifurcation { .. } => "Bifurcation", | ||
Self::ConstantSpline { .. } => "Constant Spline", | ||
Self::LinearSpline { .. } => "Linear Spline", | ||
Self::LinearSplineAuto { .. } => "Linear Spline [auto]", | ||
Self::QuadraticSpline { .. } => "Quadratic Spline", | ||
}; | ||
write!(fmt, "{}", kind) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
//! Mathematical function module. | ||
|
||
pub mod formula; | ||
pub mod formula_builder; | ||
|
||
pub use self::{formula::*, formula_builder::*}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,10 @@ | ||
//! Mathematics module. | ||
|
||
pub mod alias; | ||
pub mod func; | ||
pub mod linalg; | ||
|
||
pub mod rng; | ||
pub mod slice; | ||
pub mod trans3_builder; | ||
|
||
pub use self::{alias::*, linalg::*, trans3_builder::*}; | ||
pub use self::{alias::*, func::*, linalg::*, rng::*, slice::*, trans3_builder::*}; |
Oops, something went wrong.