use crate::DType;
use numr::runtime::Runtime;
use numr::tensor::Tensor;
#[derive(Debug, Clone)]
pub struct QuadOptions {
pub rtol: f64,
pub atol: f64,
pub limit: usize,
}
impl Default for QuadOptions {
fn default() -> Self {
Self {
rtol: 1e-8,
atol: 1e-8,
limit: 50,
}
}
}
#[derive(Debug, Clone)]
pub struct QuadResult<R: Runtime<DType = DType>> {
pub integral: Tensor<R>,
pub error: f64,
pub neval: usize,
pub converged: bool,
}
#[derive(Debug, Clone)]
pub struct RombergOptions {
pub rtol: f64,
pub atol: f64,
pub max_levels: usize,
}
impl Default for RombergOptions {
fn default() -> Self {
Self {
rtol: 1e-8,
atol: 1e-8,
max_levels: 20,
}
}
}
#[derive(Debug, Clone)]
pub struct TanhSinhOptions {
pub rtol: f64,
pub atol: f64,
pub max_levels: usize,
}
impl Default for TanhSinhOptions {
fn default() -> Self {
Self {
rtol: 1e-8,
atol: 1e-8,
max_levels: 10,
}
}
}
impl TanhSinhOptions {
pub fn with_tolerances(rtol: f64, atol: f64) -> Self {
Self {
rtol,
atol,
..Default::default()
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum MonteCarloMethod {
#[default]
Plain,
Stratified {
n_strata: usize,
},
Antithetic,
}
#[derive(Debug, Clone)]
pub struct MonteCarloOptions {
pub n_samples: usize,
pub method: MonteCarloMethod,
pub seed: Option<u64>,
}
impl Default for MonteCarloOptions {
fn default() -> Self {
Self {
n_samples: 10000,
method: MonteCarloMethod::Plain,
seed: None,
}
}
}
impl MonteCarloOptions {
pub fn with_samples(n_samples: usize) -> Self {
Self {
n_samples,
..Default::default()
}
}
pub fn method(mut self, method: MonteCarloMethod) -> Self {
self.method = method;
self
}
pub fn seed(mut self, seed: u64) -> Self {
self.seed = Some(seed);
self
}
}
#[derive(Debug, Clone)]
pub struct MonteCarloResult<R: Runtime<DType = DType>> {
pub integral: Tensor<R>,
pub std_error: f64,
pub n_samples: usize,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum QMCSequence {
#[default]
Sobol,
Halton,
}
#[derive(Debug, Clone)]
pub struct QMCOptions {
pub n_samples: usize,
pub sequence: QMCSequence,
pub skip: usize,
}
impl Default for QMCOptions {
fn default() -> Self {
Self {
n_samples: 10000,
sequence: QMCSequence::Sobol,
skip: 0,
}
}
}
impl QMCOptions {
pub fn with_samples(n_samples: usize) -> Self {
Self {
n_samples,
..Default::default()
}
}
pub fn sequence(mut self, sequence: QMCSequence) -> Self {
self.sequence = sequence;
self
}
}
#[derive(Debug, Clone)]
pub struct NQuadOptions {
pub rtol: f64,
pub atol: f64,
pub limit: usize,
}
impl Default for NQuadOptions {
fn default() -> Self {
Self {
rtol: 1e-8,
atol: 1e-8,
limit: 50,
}
}
}
impl NQuadOptions {
pub fn with_tolerances(rtol: f64, atol: f64) -> Self {
Self {
rtol,
atol,
..Default::default()
}
}
}
#[derive(Debug, Clone)]
pub struct BVPResult<R: Runtime<DType = DType>> {
pub x: Tensor<R>,
pub y: Tensor<R>,
pub residual: Tensor<R>,
pub success: bool,
pub niter: usize,
pub mesh_size: usize,
pub message: Option<String>,
}
impl<R: Runtime<DType = DType>> BVPResult<R> {
pub fn y_left(&self) -> Vec<f64> {
let shape = self.y.shape();
if shape.len() != 2 || shape[1] == 0 {
return vec![];
}
let n_vars = shape[0];
let all_data: Vec<f64> = self.y.to_vec();
all_data
.iter()
.step_by(shape[1])
.take(n_vars)
.copied()
.collect()
}
pub fn y_right(&self) -> Vec<f64> {
let shape = self.y.shape();
if shape.len() != 2 || shape[1] == 0 {
return vec![];
}
let n_vars = shape[0];
let n_points = shape[1];
let all_data: Vec<f64> = self.y.to_vec();
(0..n_vars)
.map(|i| all_data[i * n_points + n_points - 1])
.collect()
}
}
#[derive(Debug, Clone)]
pub struct SymplecticResult<R: Runtime<DType = DType>> {
pub t: Tensor<R>,
pub q: Tensor<R>,
pub p: Tensor<R>,
pub energy: Option<Tensor<R>>,
pub nsteps: usize,
}