use num::Complex;
pub struct Polynomial<const N: usize> {
coeff: [f64; N],
}
impl<const N: usize> Polynomial<N> {
pub fn new(coeff: [f64; N]) -> Self {
Polynomial { coeff }
}
pub fn from_slice(coeff: &[f64]) -> Self {
assert_eq!(coeff.len(), N);
let mut arr = [0.0; N];
for i in 0..coeff.len() {
arr[i] = coeff[i];
}
Polynomial { coeff: arr }
}
pub fn eval(&self, x: f64) -> f64 {
let mut val = 0.0;
for i in (0..N).rev() {
val = self.coeff[i] + x * val;
}
val
}
}
pub fn gamma(z0: Complex<f64>) -> Complex<f64> {
let pi = std::f64::consts::PI;
let coeffs = [
0.99999999999980993,
676.5203681218851,
-1259.1392167224028,
771.32342877765313,
-176.61502916214059,
12.507343278686905,
-0.13857109526572012,
9.9843695780195716e-6,
1.5056327351493116e-7,
];
if z0.re < 0.5 {
return pi / ((pi * z0).sin() * gamma(1.0 - z0));
}
let z = z0 - 1.0;
let mut x = Complex::new(coeffs[0], 0.0);
for i in 1..coeffs.len() {
x += coeffs[i] / (z + i as f64);
}
let t = z + 7.5;
f64::sqrt(2.0 * pi) * t.powc(z + 0.5) * (-t).exp() * x
}
pub fn beta(z: Complex<f64>, w: Complex<f64>) -> Complex<f64> {
gamma(z) * gamma(w) / gamma(z + w)
}
pub fn factorial(n: i64) -> i64 {
let z: Complex<f64> = Complex::new((n + 1) as f64, 0.0);
let res = gamma(z);
res.re.round() as i64
}
pub fn binomial(n: i64, k: i64) -> i64 {
if k > n {
return 0;
}
factorial(n) / (factorial(k) * factorial(n - k))
}
pub fn fibonacci(n: i32) -> f64 {
let phi = 1.618033988749894848204586834365638118_f64;
(phi.powi(n) / 5.0_f64.sqrt()).round().try_into().unwrap()
}
pub fn ln(x: f64, iter: i32) -> f64 {
let mut sum = 0.0;
for i in 0..iter {
sum += (-1.0_f64).powi(i + 1) * (x - 1.0).powi(i) / i as f64;
}
sum
}
pub fn sqrt(x: f64, iter: usize) -> f64 {
let mut y = 1.0;
for _ in 0..iter {
y = y - (y * y - x) / (2.0 * y);
}
y
}
pub fn pow(x: f64, n: i32) -> f64 {
if n == 0 {
return 1.0;
}
let t = pow(x, n / 2);
if n % 2 == 0 {
t * t
} else {
x * t * t
}
}
pub fn sin(x: f64, iter: i32) -> f64 {
let pi_2 = 2.0 * std::f64::consts::PI;
let mut y = 0.0;
let mut x = x;
while x > pi_2 {
x -= pi_2;
}
for i in (1..iter).step_by(2) {
y += (-1.0_f64).powf(i as f64 / 2.0) / factorial(i as i64) as f64 * x.powi(i);
}
y
}
pub fn cos(x: f64, iter: i32) -> f64 {
let pi_2 = 2.0 * std::f64::consts::PI;
let mut y = 1.0;
let mut x = x;
while x > pi_2 {
x -= pi_2;
}
for i in (2..iter).step_by(2) {
y += (-1.0_f64).powf(i as f64 / 2.0) / factorial(i as i64) as f64 * x.powi(i);
}
y
}