use crate::errors::RocheError;
use pyo3::prelude::*;
#[pyfunction]
#[pyo3(name = "xl1")]
pub fn x_l1(q: f64) -> Result<f64, RocheError> {
const NMAX: i32 = 1000;
const EPS: f64 = 1.0e-12;
if q <= 0.0 {
let message = format!("q = {} <= 0", q);
return Err(RocheError::ParameterError(message));
}
let mu: f64 = q / (1.0 + q);
let a1: f64 = -1.0 + mu;
let a2: f64 = 2.0 - 2. * mu;
let a3: f64 = -1.0 + mu;
let a4: f64 = 1.0 + 2. * mu;
let a5: f64 = -2.0 - mu;
let a6: f64 = 1.0;
let d1: f64 = 1.0 * a2;
let d2: f64 = 2.0 * a3;
let d3: f64 = 3.0 * a4;
let d4: f64 = 4.0 * a5;
let d5: f64 = 5.0 * a6;
let mut n: i32 = 0;
let mut xold: f64 = 0.;
let mut x: f64 = 1. / (1.0 + q);
let mut f: f64;
let mut df: f64;
while n < NMAX && (x - xold).abs() > EPS * x.abs() {
xold = x;
f = x * (x * (x * (x * (x * a6 + a5) + a4) + a3) + a2) + a1;
df = x * (x * (x * (x * d5 + d4) + d3) + d2) + d1;
x -= f / df;
n += 1;
}
Ok(x)
}
#[pyfunction]
#[pyo3(name = "xl11")]
pub fn x_l1_1(q: f64, spin: f64) -> Result<f64, RocheError> {
const NMAX: i32 = 1000;
const EPS: f64 = 1.0e-12;
if q <= 0.0 {
let message = format!("q = {} <= 0", q);
return Err(RocheError::ParameterError(message));
}
let spin_squared: f64 = spin * spin;
let mu: f64 = q / (1.0 + q);
let a1: f64 = -1.0 + mu;
let a2: f64 = 2.0 - 2. * mu;
let a3: f64 = -1.0 + mu;
let a4: f64 = spin_squared + 2. * mu;
let a5: f64 = -2. * spin_squared - mu;
let a6: f64 = spin_squared;
let d1: f64 = 1. * a2;
let d2: f64 = 2. * a3;
let d3: f64 = 3. * a4;
let d4: f64 = 4. * a5;
let d5: f64 = 5. * a6;
let mut n: i32 = 0;
let mut xold: f64 = 0.;
let mut x: f64 = 1. / (1.0 + q);
let mut f: f64;
let mut df: f64;
while n < NMAX && (x - xold).abs() > EPS * x.abs() {
xold = x;
f = x * (x * (x * (x * (x * a6 + a5) + a4) + a3) + a2) + a1;
df = x * (x * (x * (x * d5 + d4) + d3) + d2) + d1;
x -= f / df;
n += 1;
}
Ok(x)
}
#[pyfunction]
#[pyo3(name = "xl12")]
pub fn x_l1_2(q: f64, spin: f64) -> Result<f64, RocheError> {
const NMAX: i32 = 1000;
const EPS: f64 = 1.0e-12;
if q <= 0.0 {
let message = format!("q = {} <= 0", q);
return Err(RocheError::ParameterError(message));
}
let spin_squared: f64 = spin * spin;
let mu: f64 = q / (1.0 + q);
let a1: f64 = -1.0 + mu;
let a2: f64 = 2.0 - 2. * mu;
let a3: f64 = -spin_squared + mu;
let a4: f64 = 3. * spin_squared + 2. * mu - 2.;
let a5: f64 = 1.0 - mu - 3. * spin_squared;
let a6: f64 = spin_squared;
let d1: f64 = 1. * a2;
let d2: f64 = 2. * a3;
let d3: f64 = 3. * a4;
let d4: f64 = 4. * a5;
let d5: f64 = 5. * a6;
let mut n: i32 = 0;
let mut xold: f64 = 0.;
let mut x: f64 = 1. / (1.0 + q);
let mut f: f64;
let mut df: f64;
while n < NMAX && (x - xold).abs() > EPS * x.abs() {
xold = x;
f = x * (x * (x * (x * (x * a6 + a5) + a4) + a3) + a2) + a1;
df = x * (x * (x * (x * d5 + d4) + d3) + d2) + d1;
x -= f / df;
n += 1;
}
Ok(x)
}
#[pyfunction]
#[pyo3(name = "xl2")]
pub fn x_l2(q: f64) -> Result<f64, RocheError> {
const NMAX: i32 = 1000;
const EPS: f64 = 1.0e-12;
if q <= 0.0 {
let message = format!("q = {} <= 0", q);
return Err(RocheError::ParameterError(message));
}
let mu = q / (1.0 + q);
let a1 = -1.0 + mu;
let a2 = 2.0 - 2. * mu;
let a3 = -1.0 - mu;
let a4 = 1.0 + 2. * mu;
let a5 = -2.0 - mu;
let a6 = 1.;
let d1 = 1. * a2;
let d2 = 2. * a3;
let d3 = 3. * a4;
let d4 = 4. * a5;
let d5 = 5. * a6;
let mut n: i32 = 0;
let mut xold: f64 = 0.;
let mut x: f64 = 1.5;
let mut f: f64;
let mut df: f64;
while n < NMAX && (x - xold).abs() > EPS * x.abs() {
xold = x;
f = x * (x * (x * (x * (x * a6 + a5) + a4) + a3) + a2) + a1;
df = x * (x * (x * (x * d5 + d4) + d3) + d2) + d1;
x -= f / df;
n += 1;
}
Ok(x)
}
#[pyfunction]
#[pyo3(name = "xl3")]
pub fn x_l3(q: f64) -> Result<f64, RocheError> {
const NMAX: i32 = 1000;
const EPS: f64 = 1.0e-12;
if q <= 0.0 {
let message = format!("q = {} <= 0", q);
return Err(RocheError::ParameterError(message));
}
let mu = q / (1.0 + q);
let a1 = 1.0 - mu;
let a2 = -2.0 + 2. * mu;
let a3 = 1.0 - mu;
let a4 = 1.0 + 2. * mu;
let a5 = -2.0 - mu;
let a6 = 1.;
let d1 = 1. * a2;
let d2 = 2. * a3;
let d3 = 3. * a4;
let d4 = 4. * a5;
let d5 = 5. * a6;
let mut n: i32 = 0;
let mut xold: f64 = 0.;
let mut x: f64 = -1.;
let mut f: f64;
let mut df: f64;
while n < NMAX && (x - xold).abs() > EPS * x.abs() {
xold = x;
f = x * (x * (x * (x * (x * a6 + a5) + a4) + a3) + a2) + a1;
df = x * (x * (x * (x * d5 + d4) + d3) + d2) + d1;
x -= f / df;
n += 1;
}
Ok(x)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn xl1() -> Result<(), RocheError> {
assert_eq!(x_l1(0.2)?, 0.6585556789537762);
assert!(x_l1(-0.2).is_err());
Ok(())
}
#[test]
fn xl11() -> Result<(), RocheError> {
assert_eq!(x_l1_1(0.2, 0.5)?, 0.6906163968474123);
assert!(x_l1_1(-0.2, 0.5).is_err());
Ok(())
}
#[test]
fn xl12() -> Result<(), RocheError> {
assert_eq!(x_l1_2(0.2, 0.5)?, 0.6403753216278784);
assert!(x_l1_2(-0.2, 0.5).is_err());
Ok(())
}
#[test]
fn xl2() -> Result<(), RocheError> {
assert_eq!(x_l2(0.2)?, 1.4380767810774817);
assert!(x_l2(-0.2).is_err());
Ok(())
}
#[test]
fn xl3() -> Result<(), RocheError> {
assert_eq!(x_l3(0.2)?, -0.9024984464339775);
assert!(x_l3(-0.2).is_err());
Ok(())
}
}