use crate::qtty::*;
#[derive(Debug, Clone, Copy)]
pub struct SearchOpts {
pub time_tolerance: Days,
}
impl Default for SearchOpts {
fn default() -> Self {
Self {
time_tolerance: DEFAULT_TIME_TOLERANCE,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub(crate) struct ChebyshevSearchConfig {
pub segment_length: Days,
pub degree: usize,
pub max_tail_norm: f64,
pub max_residual: f64,
pub refine: bool,
pub refine_margin: Days,
pub min_slope: f64,
pub adaptive_split: bool,
pub max_split_depth: usize,
}
impl Default for ChebyshevSearchConfig {
fn default() -> Self {
Self {
segment_length: Hours::new(12.0).to::<Day>(),
degree: 10,
max_tail_norm: 1e-6,
max_residual: 1e-10,
refine: true,
refine_margin: Minutes::new(20.0).to::<Day>(),
min_slope: 1e-8,
adaptive_split: true,
max_split_depth: 2,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub(crate) struct FallbackSearchConfig {
pub scan_step: Option<Days>,
pub force_scan_baseline: bool,
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct InternalSearchConfig {
pub time_tolerance: Days,
pub chebyshev: ChebyshevSearchConfig,
pub fallback: FallbackSearchConfig,
pub disable_solar_daily_predictor: bool,
}
impl InternalSearchConfig {
#[inline]
pub(crate) fn from_public_opts(opts: SearchOpts) -> Self {
Self {
time_tolerance: opts.time_tolerance,
chebyshev: ChebyshevSearchConfig::default(),
fallback: FallbackSearchConfig::default(),
disable_solar_daily_predictor: false,
}
}
#[inline]
pub(crate) fn uses_scan_baseline(self) -> bool {
self.fallback.force_scan_baseline
}
#[inline]
pub(crate) fn fallback_scan_step(self, default_step: Days) -> Days {
self.fallback.scan_step.unwrap_or(default_step)
}
#[cfg(any(test, feature = "bench-internals"))]
pub(crate) fn scan_brent_baseline_config(opts: SearchOpts) -> Self {
Self {
time_tolerance: opts.time_tolerance,
chebyshev: ChebyshevSearchConfig::default(),
fallback: FallbackSearchConfig {
scan_step: Some(DEFAULT_SCAN_STEP),
force_scan_baseline: true,
},
disable_solar_daily_predictor: true,
}
}
#[cfg(feature = "bench-internals")]
pub(crate) fn chebyshev_baseline_config(opts: SearchOpts) -> Self {
Self {
time_tolerance: opts.time_tolerance,
chebyshev: ChebyshevSearchConfig::default(),
fallback: FallbackSearchConfig::default(),
disable_solar_daily_predictor: true,
}
}
}
impl Default for InternalSearchConfig {
fn default() -> Self {
Self::from_public_opts(SearchOpts::default())
}
}
pub(crate) fn resolve_scan_step(
hint: Option<Days>,
opts: &InternalSearchConfig,
default_step: Days,
) -> Days {
opts.fallback.scan_step.or(hint).unwrap_or(default_step)
}
pub(crate) const ONE_DAY: Days = Days::new(1.0);
pub(crate) const DEFAULT_TIME_TOLERANCE: Days = Days::new(1e-9);
pub(crate) const ROOT_INTERVAL_EPS: Days = Days::new(1e-12);
pub(crate) const CROSSING_DEDUPE_EPS: Days = Days::new(1e-8);
pub(crate) const DIURNAL_CHEBY_SCAN_STEP: Days = Hours::new(2.0).to_const::<Day>();
pub(crate) const DEFAULT_SCAN_STEP: Days = Minutes::new(10.0).to_const::<Day>();
pub(crate) const EXTREMA_SCAN_STEP: Days = Minutes::new(20.0).to_const::<Day>();