use integral::math::am::{cart_components, n_cart};
use integral::math::norm::{cart_norm, double_factorial};
use integral::math::solid_harmonics::{c2s_matrix, monomial_to_raw_factor};
fn pi() -> f64 {
std::f64::consts::PI
}
fn moment(n: usize, beta: f64) -> f64 {
if n % 2 == 1 {
return 0.0;
}
double_factorial(n as i64 - 1) / (2.0 * beta).powi(n as i32 / 2) * (pi() / beta).sqrt()
}
fn s_mono(l: usize) -> Vec<f64> {
let comps = cart_components(l);
let nc = n_cart(l);
let nshell = cart_norm(1.0, l, 0, 0);
let beta = 2.0;
let mut s = vec![0.0; nc * nc];
for (i, ci) in comps.iter().enumerate() {
for (j, cj) in comps.iter().enumerate() {
let bare = moment(ci[0] + cj[0], beta)
* moment(ci[1] + cj[1], beta)
* moment(ci[2] + cj[2], beta);
s[i * nc + j] = nshell * nshell * bare;
}
}
s
}
#[test]
fn factor1_is_closed_form_in_isolation() {
assert_eq!(monomial_to_raw_factor(0), 1.0);
assert_eq!(monomial_to_raw_factor(1), 1.0);
for l in 2..=6 {
let want = (4.0 * pi() / (2 * l + 1) as f64).sqrt();
assert!((monomial_to_raw_factor(l) - want).abs() < 1e-15, "l={l}");
}
}
#[test]
fn c2s_unit_in_raw_metric_and_composed_unit_in_monomial_metric() {
for l in 0..=6 {
let nc = n_cart(l);
let nsph = 2 * l + 1;
let c = c2s_matrix(l);
let ratio = monomial_to_raw_factor(l);
let smono = s_mono(l);
let sraw: Vec<f64> = smono.iter().map(|&v| ratio * ratio * v).collect();
let m: Vec<f64> = c.iter().map(|&v| ratio * v).collect();
let gram = |t: &[f64], s: &[f64]| {
let mut g = vec![0.0; nsph * nsph];
for p in 0..nsph {
for q in 0..nsph {
let mut acc = 0.0;
for i in 0..nc {
let mut si = 0.0;
for j in 0..nc {
si += s[i * nc + j] * t[q * nc + j];
}
acc += t[p * nc + i] * si;
}
g[p * nsph + q] = acc;
}
}
g
};
let g_raw = gram(&c, &sraw);
let g_mono = gram(&m, &smono);
for p in 0..nsph {
for q in 0..nsph {
let e = if p == q { 1.0 } else { 0.0 };
assert!(
(g_raw[p * nsph + q] - e).abs() < 1e-11,
"l={l} C·S_raw·Cᵀ[{p},{q}]"
);
assert!(
(g_mono[p * nsph + q] - e).abs() < 1e-11,
"l={l} M·S_mono·Mᵀ[{p},{q}]"
);
}
}
}
}
#[test]
fn composed_transform_is_independent_of_factor_value() {
for l in 2..=6 {
let nc = n_cart(l);
let c = c2s_matrix(l);
let ratio = monomial_to_raw_factor(l);
let smono = s_mono(l);
for p in 0..(2 * l + 1) {
let crow = &c[p * nc..(p + 1) * nc];
let mut q = 0.0;
for i in 0..nc {
for j in 0..nc {
q += crow[i] * crow[j] * smono[i * nc + j];
}
}
let kappa = 1.0 / q.sqrt(); for (i, &ci) in crow.iter().enumerate() {
let m_production = ratio * ci;
let m_from_mono = kappa * ci;
assert!(
(m_production - m_from_mono).abs() < 1e-11,
"l={l} p={p} i={i}: ratio·c={m_production} vs mono-norm={m_from_mono} \
— composed transform is NOT ratio-independent"
);
}
}
}
}