use num_traits::Float;
use crate::{
float::SemiflowFloat,
grid::{bc_value_generic, BoundaryPolicy, Grid1D},
};
#[allow(clippy::inline_always)]
#[inline(always)]
fn fc<F: SemiflowFloat>(v: f64) -> F {
F::from(v).unwrap_or_else(F::zero)
}
#[inline]
fn h_a0_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s5 * ((((-fc::<F>(70.0) * s + fc::<F>(315.0)) * s - fc::<F>(540.0)) * s + fc::<F>(420.0)) * s
- fc::<F>(126.0))
+ F::one()
}
#[inline]
fn h_a1_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s + s5
* ((((-fc::<F>(35.0) * s + fc::<F>(160.0)) * s - fc::<F>(280.0)) * s + fc::<F>(224.0)) * s
- fc::<F>(70.0))
}
#[inline]
fn h_a2_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
fc::<F>(0.5) * s2
+ s5 * ((((-fc::<F>(7.5) * s + fc::<F>(35.0)) * s - fc::<F>(63.0)) * s + fc::<F>(52.5)) * s
- fc::<F>(17.5))
}
#[inline]
fn h_a3_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s3 = s2 * s;
let s5 = s2 * s3;
fc::<F>(1.0 / 6.0) * s3
+ s5 * ((((-fc::<F>(5.0 / 6.0) * s + fc::<F>(4.0)) * s - fc::<F>(7.5)) * s
+ fc::<F>(20.0 / 3.0))
* s
- fc::<F>(2.5))
}
#[inline]
fn h_a4_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s4 = s2 * s2;
let s5 = s4 * s;
fc::<F>(1.0 / 24.0) * s4
+ s5 * ((((-fc::<F>(1.0 / 24.0) * s + fc::<F>(5.0 / 24.0)) * s - fc::<F>(5.0 / 12.0)) * s
+ fc::<F>(5.0 / 12.0))
* s
- fc::<F>(5.0 / 24.0))
}
#[inline]
fn h_b0_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s5 * ((((fc::<F>(70.0) * s - fc::<F>(315.0)) * s + fc::<F>(540.0)) * s - fc::<F>(420.0)) * s
+ fc::<F>(126.0))
}
#[inline]
fn h_b1_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s5 * ((((-fc::<F>(35.0) * s + fc::<F>(155.0)) * s - fc::<F>(260.0)) * s + fc::<F>(196.0)) * s
- fc::<F>(56.0))
}
#[inline]
fn h_b2_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s5 * ((((fc::<F>(7.5) * s - fc::<F>(32.5)) * s + fc::<F>(53.0)) * s - fc::<F>(38.5)) * s
+ fc::<F>(10.5))
}
#[inline]
fn h_b3_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s5 * ((((-fc::<F>(5.0 / 6.0) * s + fc::<F>(3.5)) * s - fc::<F>(5.5)) * s + fc::<F>(23.0 / 6.0))
* s
- F::one())
}
#[inline]
fn h_b4_g<F: SemiflowFloat>(s: F) -> F {
let s2 = s * s;
let s5 = s2 * s2 * s;
s5 * ((((fc::<F>(1.0 / 24.0) * s - fc::<F>(1.0 / 6.0)) * s + fc::<F>(0.25)) * s
- fc::<F>(1.0 / 6.0))
* s
+ fc::<F>(1.0 / 24.0))
}
#[allow(clippy::similar_names)]
#[inline]
fn fd_prime_g<F: SemiflowFloat>(
values: &[F],
bnd: BoundaryPolicy<F>,
n: usize,
idx: i64,
dx: F,
) -> F {
let fm5 = bc_value_generic(bnd, values, n, idx - 5, dx);
let fm4 = bc_value_generic(bnd, values, n, idx - 4, dx);
let fm3 = bc_value_generic(bnd, values, n, idx - 3, dx);
let fm2 = bc_value_generic(bnd, values, n, idx - 2, dx);
let fm1 = bc_value_generic(bnd, values, n, idx - 1, dx);
let fp1 = bc_value_generic(bnd, values, n, idx + 1, dx);
let fp2 = bc_value_generic(bnd, values, n, idx + 2, dx);
let fp3 = bc_value_generic(bnd, values, n, idx + 3, dx);
let fp4 = bc_value_generic(bnd, values, n, idx + 4, dx);
let fp5 = bc_value_generic(bnd, values, n, idx + 5, dx);
(-fc::<F>(2.0) * fm5 + fc::<F>(25.0) * fm4 - fc::<F>(150.0) * fm3 + fc::<F>(600.0) * fm2
- fc::<F>(2100.0) * fm1
+ fc::<F>(2100.0) * fp1
- fc::<F>(600.0) * fp2
+ fc::<F>(150.0) * fp3
- fc::<F>(25.0) * fp4
+ fc::<F>(2.0) * fp5)
/ fc::<F>(2520.0)
}
#[allow(clippy::similar_names)]
#[inline]
fn fd_double_g<F: SemiflowFloat>(
values: &[F],
bnd: BoundaryPolicy<F>,
n: usize,
idx: i64,
dx: F,
) -> F {
let fm4 = bc_value_generic(bnd, values, n, idx - 4, dx);
let fm3 = bc_value_generic(bnd, values, n, idx - 3, dx);
let fm2 = bc_value_generic(bnd, values, n, idx - 2, dx);
let fm1 = bc_value_generic(bnd, values, n, idx - 1, dx);
let f0 = bc_value_generic(bnd, values, n, idx, dx);
let fp1 = bc_value_generic(bnd, values, n, idx + 1, dx);
let fp2 = bc_value_generic(bnd, values, n, idx + 2, dx);
let fp3 = bc_value_generic(bnd, values, n, idx + 3, dx);
let fp4 = bc_value_generic(bnd, values, n, idx + 4, dx);
(-fc::<F>(9.0) * fm4 + fc::<F>(128.0) * fm3 - fc::<F>(1008.0) * fm2 + fc::<F>(8064.0) * fm1
- fc::<F>(14350.0) * f0
+ fc::<F>(8064.0) * fp1
- fc::<F>(1008.0) * fp2
+ fc::<F>(128.0) * fp3
- fc::<F>(9.0) * fp4)
/ fc::<F>(5040.0)
}
#[allow(clippy::similar_names)]
#[inline]
fn fd_triple_g<F: SemiflowFloat>(
values: &[F],
bnd: BoundaryPolicy<F>,
n: usize,
idx: i64,
dx: F,
) -> F {
let fm5 = bc_value_generic(bnd, values, n, idx - 5, dx);
let fm4 = bc_value_generic(bnd, values, n, idx - 4, dx);
let fm3 = bc_value_generic(bnd, values, n, idx - 3, dx);
let fm2 = bc_value_generic(bnd, values, n, idx - 2, dx);
let fm1 = bc_value_generic(bnd, values, n, idx - 1, dx);
let fp1 = bc_value_generic(bnd, values, n, idx + 1, dx);
let fp2 = bc_value_generic(bnd, values, n, idx + 2, dx);
let fp3 = bc_value_generic(bnd, values, n, idx + 3, dx);
let fp4 = bc_value_generic(bnd, values, n, idx + 4, dx);
let fp5 = bc_value_generic(bnd, values, n, idx + 5, dx);
(fc::<F>(205.0) * fm5 - fc::<F>(2522.0) * fm4 + fc::<F>(14607.0) * fm3 - fc::<F>(52428.0) * fm2
+ fc::<F>(70098.0) * fm1
- fc::<F>(70098.0) * fp1
+ fc::<F>(52428.0) * fp2
- fc::<F>(14607.0) * fp3
+ fc::<F>(2522.0) * fp4
- fc::<F>(205.0) * fp5)
/ fc::<F>(30240.0)
}
#[allow(clippy::similar_names)]
#[inline]
fn fd_quad_g<F: SemiflowFloat>(
values: &[F],
bnd: BoundaryPolicy<F>,
n: usize,
idx: i64,
dx: F,
) -> F {
let fm4 = bc_value_generic(bnd, values, n, idx - 4, dx);
let fm3 = bc_value_generic(bnd, values, n, idx - 3, dx);
let fm2 = bc_value_generic(bnd, values, n, idx - 2, dx);
let fm1 = bc_value_generic(bnd, values, n, idx - 1, dx);
let f0 = bc_value_generic(bnd, values, n, idx, dx);
let fp1 = bc_value_generic(bnd, values, n, idx + 1, dx);
let fp2 = bc_value_generic(bnd, values, n, idx + 2, dx);
let fp3 = bc_value_generic(bnd, values, n, idx + 3, dx);
let fp4 = bc_value_generic(bnd, values, n, idx + 4, dx);
(fc::<F>(7.0) * fm4 - fc::<F>(96.0) * fm3 + fc::<F>(676.0) * fm2 - fc::<F>(1952.0) * fm1
+ fc::<F>(2730.0) * f0
- fc::<F>(1952.0) * fp1
+ fc::<F>(676.0) * fp2
- fc::<F>(96.0) * fp3
+ fc::<F>(7.0) * fp4)
/ fc::<F>(240.0)
}
pub(crate) fn sample_octonic_1d_generic<F: SemiflowFloat>(
values: &[F],
grid: &Grid1D<F>,
x: F,
) -> F {
let dx = grid.dx();
let t_frac = (x - grid.xmin) / dx;
let t_floor = Float::floor(t_frac);
#[allow(clippy::cast_possible_truncation)]
let idx = t_floor.to_i64().unwrap_or(0);
let s = t_frac - t_floor;
let bnd = grid.boundary;
let n = grid.n;
let v0 = bc_value_generic(bnd, values, n, idx, dx);
let v1 = bc_value_generic(bnd, values, n, idx + 1, dx);
let v0p = fd_prime_g(values, bnd, n, idx, dx);
let v1p = fd_prime_g(values, bnd, n, idx + 1, dx);
let v0pp = fd_double_g(values, bnd, n, idx, dx);
let v1pp = fd_double_g(values, bnd, n, idx + 1, dx);
let v0ppp = fd_triple_g(values, bnd, n, idx, dx);
let v1ppp = fd_triple_g(values, bnd, n, idx + 1, dx);
let v0pppp = fd_quad_g(values, bnd, n, idx, dx);
let v1pppp = fd_quad_g(values, bnd, n, idx + 1, dx);
h_a0_g(s) * v0
+ h_a1_g(s) * v0p
+ h_a2_g(s) * v0pp
+ h_a3_g(s) * v0ppp
+ h_a4_g(s) * v0pppp
+ h_b0_g(s) * v1
+ h_b1_g(s) * v1p
+ h_b2_g(s) * v1pp
+ h_b3_g(s) * v1ppp
+ h_b4_g(s) * v1pppp
}