use num::{complex::Complex, Zero};
use std::collections::HashMap;
use crate::harmonics::{g_functions, w1, w2, w3, w4, w5};
#[derive(Debug, PartialEq, Eq, Hash)]
pub enum K {
S1,
S2,
S3,
S4,
S5,
S1h,
S2h,
S3h,
S1mh,
S2mh,
S3mh,
G3,
Sm1e,
Sm1o,
Sm2e,
Sm2o,
Sm3e,
Sm3o,
Sm21e,
Sm21o,
}
pub struct Cache {
n: Complex<f64>,
m: HashMap<K, Complex<f64>>,
}
impl Cache {
pub fn new(n: Complex<f64>) -> Self {
Self {
n,
m: HashMap::new(),
}
}
pub fn n(&self) -> Complex<f64> {
Complex::new(self.n.re, self.n.im)
}
pub fn get(&mut self, k: K) -> Complex<f64> {
let val = self.m.get(&k);
if let Some(value) = val {
return *value;
}
let val = match k {
K::S1 => w1::S1(self.n),
K::S2 => w2::S2(self.n),
K::S3 => w3::S3(self.n),
K::S4 => w4::S4(self.n),
K::S5 => w5::S5(self.n),
K::S1h => w1::S1(self.n / 2.),
K::S2h => w2::S2(self.n / 2.),
K::S3h => w3::S3(self.n / 2.),
K::S1mh => w1::S1((self.n - 1.) / 2.),
K::S2mh => w2::S2((self.n - 1.) / 2.),
K::S3mh => w3::S3((self.n - 1.) / 2.),
K::G3 => g_functions::g3(self),
K::Sm1e => w1::Sm1e(self),
K::Sm1o => w1::Sm1o(self),
K::Sm2e => w2::Sm2e(self),
K::Sm2o => w2::Sm2o(self),
K::Sm3e => w3::Sm3e(self),
K::Sm3o => w3::Sm3o(self),
K::Sm21e => w3::Sm21e(self),
K::Sm21o => w3::Sm21o(self),
};
self.m.insert(k, val);
val
}
}
pub fn recursive_harmonic_sum(
base_value: Complex<f64>,
n: Complex<f64>,
iterations: usize,
weight: u32,
) -> Complex<f64> {
let mut fact = Complex::zero();
for i in 1..iterations + 1 {
fact += (1.0 / (n + (i as f64))).powu(weight);
}
base_value + fact
}
#[cfg(test)]
mod tests {
use super::*;
use crate::harmonics::{w1, w2, w3, w4};
use crate::{assert_approx_eq_cmplx, cmplx};
use num::complex::Complex;
#[test]
fn n() {
let n = cmplx!(1., 0.);
let c = Cache::new(n);
let mut m = c.n();
m += cmplx!(1., 0.);
assert_approx_eq_cmplx!(f64, c.n(), n);
assert_approx_eq_cmplx!(f64, m, cmplx!(2., 0.));
}
#[test]
fn test_recursive_harmonic_sum() {
const SX: [fn(Complex<f64>) -> Complex<f64>; 5] = [w1::S1, w2::S2, w3::S3, w4::S4, w5::S5];
const NS: [Complex<f64>; 2] = [cmplx!(1.0, 0.0), cmplx!(2.34, 3.45)];
const ITERS: [usize; 2] = [1, 2];
for sit in SX.iter().enumerate() {
for nit in NS.iter().enumerate() {
let n = *nit.1;
for iit in ITERS.iter().enumerate() {
let iterations = *iit.1;
let s_base = sit.1(n);
let s_test = sit.1(n + (iterations as f64));
let s_ref = recursive_harmonic_sum(s_base, n, iterations, 1 + (sit.0 as u32));
assert_approx_eq_cmplx!(f64, s_test, s_ref);
}
}
}
}
}