Skip to content

Commit

Permalink
chore: clean-up code and documentation (#34)
Browse files Browse the repository at this point in the history
* rename `SimpsonsThird` to `Simpson`

* update doc

* add a `boole` feature

* add new errors
  • Loading branch information
imrn99 authored Oct 7, 2024
1 parent 02f857a commit 60cd608
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 34 deletions.
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ categories = ["algorithms", "concurrency", "mathematics", "science"]
keywords = ["algorithms", "analysis", "integration", "numerical-analysis", "numerical-method"]

[dependencies]
integraal = { workspace = true, features = ["montecarlo", "romberg"] }
integraal = { workspace = true, features = ["boole", "montecarlo", "romberg"] }
rand = { workspace = true, features = ["small_rng"] }

# EXAMPLES
Expand Down
1 change: 1 addition & 0 deletions integraal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ keywords = ["algorithms", "analysis", "integration", "numerical-analysis", "nume
# FEATURES

[features]
boole = []
montecarlo = ["dep:rand"] # gated because of additional dep
romberg = [] # gated because it is not implemented for all input kinds

Expand Down
14 changes: 14 additions & 0 deletions integraal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@
//! the example provided for the [`Integraal`] structure for a very concise overview of the crate's
//! usage.
//!
//! # Features
//!
//! ## Policy
//!
//! As a rule of thumb, a computation method will be gated behind a feature if (a) it requires
//! additional dependencies, or (b) it is not implemented for all integral definitions (e.g.
//! a method that requires a uniform domain).
//!
//! ## Feature list
//!
//! - `boole` -- enable the Boole computation method.
//! - `montecarlo` -- enable the Monte-Carlo computation method.
//! - `romberg` -- enable the Romberg computation method.
//!
//! [NI]: https://en.wikipedia.org/wiki/Numerical_integration
//! [GH]: https://github.com/imrn99/integraal

Expand Down
6 changes: 3 additions & 3 deletions integraal/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ pub enum ComputeMethod {
RectangleRight,
/// Trapezoid method -- [reference](https://en.wikipedia.org/wiki/Trapezoidal_rule)
Trapezoid,
/// Simpson's third rule -- [reference](https://en.wikipedia.org/wiki/Simpson%27s_rule),
/// [issue](https://github.com/imrn99/integraal/issues/23)
SimpsonsThird,
/// Simpson's rule(s), the exact rule applied depends on integral definition --
/// [reference](https://en.wikipedia.org/wiki/Simpson%27s_rule)
Simpson,
/// Boole's method -- [reference](https://en.wikipedia.org/wiki/Boole%27s_rule#Composite_Boole's_Rule)
Boole,
/// Romberg's method -- [reference](https://en.wikipedia.org/wiki/Romberg%27s_method#Implementation)
Expand Down
8 changes: 6 additions & 2 deletions integraal/src/structure/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,14 @@ use crate::{ComputeMethod, DomainDescriptor, FunctionDescriptor, Scalar};
/// Integral error
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum IntegraalError {
/// One or more parameters are missing.
MissingParameters(&'static str),
/// Some parameters do not fit the requirements of the computation method.
BadParameters(&'static str),
/// Specified parameters are conflicting or ambiguous.
InconsistentParameters(&'static str),
/// One or more parameters are missing.
MissingParameters(&'static str),
/// A given method isn't implemented for the specified parameters (e.g. due to requirements).
Unimplemented(&'static str),
}

/// Main integral computation structure
Expand Down
56 changes: 32 additions & 24 deletions integraal/src/structure/implementations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ fn values_explicit_arm<X: Scalar>(
(y1.min(y2) + num_traits::abs(y1 - y2) / X::from_f32(2.0).unwrap()) * step
})
.sum(),
ComputeMethod::SimpsonsThird => {
ComputeMethod::Simpson => {
// using the formula for irregularly spaced data:
// https://en.wikipedia.org/wiki/Simpson%27s_rule#Composite_Simpson's_rule_for_irregularly_spaced_data
// the formula is a sum from 0 to N-2, N the number of subintervals; so N = n_sample-1
Expand All @@ -145,13 +145,17 @@ fn values_explicit_arm<X: Scalar>(
})
.sum()
}
#[cfg(feature = "boole")]
ComputeMethod::Boole => {
// FIXME: replace by an error
unimplemented!("E: Romberg's method isn't implemented for non-uniform domains");
return Err(IntegraalError::Unimplemented(
"Boole's method isn't implemented for non-uniform domains",
));
}
#[cfg(feature = "romberg")] // FIXME: replace by an error
#[cfg(feature = "romberg")]
ComputeMethod::Romberg { .. } => {
unimplemented!("E: Romberg's method isn't implemented for non-uniform domains");
return Err(IntegraalError::Unimplemented(
"Romberg's method isn't implemented for non-uniform domains",
));
}
#[cfg(feature = "montecarlo")]
ComputeMethod::MonteCarlo { n_sample: _ } => {
Expand Down Expand Up @@ -200,7 +204,7 @@ fn values_uniform_arm<X: Scalar>(
(y1.min(y2) + (y1 - y2).abs() / X::from_f32(2.0).unwrap()) * *step
})
.sum(),
ComputeMethod::SimpsonsThird => {
ComputeMethod::Simpson => {
let indices: Vec<_> = (0..*n_step - 4).collect();
(*step / X::from(3.0).unwrap())
* indices
Expand All @@ -214,12 +218,12 @@ fn values_uniform_arm<X: Scalar>(
.sum()
}
ComputeMethod::Boole => {
// FIXME: replace with an error
assert_eq!(
*n_step % 4,
0,
"E: domain should be divided into a multiple of 4 segments for Boole's method"
);
if *n_step % 4 != 0 {
return Err(IntegraalError::BadParameters(
"domain should be divided into a multiple of 4 segments for Boole's method",
));
}

let c = X::from(2.0 / 45.0).unwrap() * *step;

let m1 = X::from(7.0).unwrap() * (vals[0] + vals[*n_step - 1]);
Expand Down Expand Up @@ -307,7 +311,7 @@ fn closure_explicit_arm<X: Scalar>(
(y1.min(y2) + (y1 - y2).abs() / X::from_f32(2.0).unwrap()) * step
})
.sum(),
ComputeMethod::SimpsonsThird => {
ComputeMethod::Simpson => {
let indices: Vec<_> = (0..args.len() - 4).collect();
indices
.windows(3)
Expand All @@ -326,13 +330,17 @@ fn closure_explicit_arm<X: Scalar>(
})
.sum()
}
#[cfg(feature = "boole")]
ComputeMethod::Boole => {
// FIXME: replace by an error
unimplemented!("E: Romberg's method isn't implemented for non-uniform domains");
return Err(IntegraalError::Unimplemented(
"Boole's method isn't implemented for non-uniform domains",
));
}
#[cfg(feature = "romberg")] // FIXME: replace by an error
#[cfg(feature = "romberg")]
ComputeMethod::Romberg { .. } => {
unimplemented!("E: Romberg's method isn't implemented for non-uniform domains");
return Err(IntegraalError::Unimplemented(
"Romberg's method isn't implemented for non-uniform domains",
));
}
#[cfg(feature = "montecarlo")]
ComputeMethod::MonteCarlo { n_sample: _ } => {
Expand Down Expand Up @@ -384,7 +392,7 @@ fn closure_uniform_arm<X: Scalar>(
(y1.min(y2) + (y1 - y2).abs() / X::from_f32(2.0).unwrap()) * *step
})
.sum(),
ComputeMethod::SimpsonsThird => {
ComputeMethod::Simpson => {
let indices: Vec<_> = (0..*n_step - 4).collect();
(*step / X::from(3.0).unwrap())
* indices
Expand All @@ -401,12 +409,12 @@ fn closure_uniform_arm<X: Scalar>(
.sum()
}
ComputeMethod::Boole => {
// FIXME: replace with an error
assert_eq!(
*n_step % 4,
0,
"E: domain should be divided into a multiple of 4 segments for Boole's method"
);
if *n_step % 4 != 0 {
return Err(IntegraalError::BadParameters(
"domain should be divided into a multiple of 4 segments for Boole's method",
));
}

let c = X::from(2.0 / 45.0).unwrap() * *step;

let m1 = X::from(7.0).unwrap()
Expand Down
9 changes: 5 additions & 4 deletions integraal/src/structure/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ mod a_simpsons3rd {
.collect(),
FunctionDescriptor::Closure(Box::new(f64::sin)),
DomainDescriptor::Explicit(&domain),
ComputeMethod::SimpsonsThird,
ComputeMethod::Simpson,
TRAPEZOID_TOLERANCE // FIXME: update tol
);

Expand All @@ -349,7 +349,7 @@ mod a_simpsons3rd {
step: STEP,
n_step: (1000. * std::f64::consts::PI) as usize,
},
ComputeMethod::SimpsonsThird,
ComputeMethod::Simpson,
TRAPEZOID_TOLERANCE // FIXME: update tol
);

Expand All @@ -360,7 +360,7 @@ mod a_simpsons3rd {
.collect(),
FunctionDescriptor::Values(domain.iter().copied().map(f64::sin).collect()),
DomainDescriptor::Explicit(&domain),
ComputeMethod::SimpsonsThird,
ComputeMethod::Simpson,
TRAPEZOID_TOLERANCE // FIXME: update tol
);

Expand All @@ -376,11 +376,12 @@ mod a_simpsons3rd {
step: STEP,
n_step: (1000. * std::f64::consts::PI) as usize,
},
ComputeMethod::SimpsonsThird,
ComputeMethod::Simpson,
TRAPEZOID_TOLERANCE // FIXME: update tol
);
}

#[cfg(feature = "boole")]
#[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
mod a_boole {
use super::*;
Expand Down

0 comments on commit 60cd608

Please sign in to comment.