use crate::Vec3;
use crate::errors::RocheError;
use crate::x_l1;
pub fn blink(q: f64, r: &Vec3, e: &Vec3, acc: f64) -> Result<bool, RocheError> {
let mut x_cofm: f64;
let mut p: f64;
let p1: f64;
let p2: f64;
let mut r1: f64;
let mut r2: f64;
if q <= 0. {
let message = format!("q = {} <= 0", q);
return Err(RocheError::ParameterError(message));
}
if acc <= 0.0 {
let message = format!("Invalid accuracy parameter. {} <= 0.0.", acc);
return Err(RocheError::ParameterError(message));
}
x_cofm = 1.0 / (1.0 + q);
let c1: f64 = 2.0 * x_cofm;
x_cofm *= q;
let c2: f64 = 2.0 * x_cofm;
let rl1: f64 = x_l1(q)?;
r1 = rl1;
r2 = 1.0 - rl1;
let xc: f64 = rl1 - x_cofm;
let crit: f64 = c1 / r1 + c2 / r2 + xc * xc;
let rsphere: f64 = 1.0 - rl1;
let pp: f64 = rsphere * rsphere;
let step: f64 = rsphere * acc;
let xt: f64 = r.x - 1.0;
let mut b: f64 = e.x * xt + e.y * r.y + e.z * r.z;
let mut c: f64 = xt * xt + r.y * r.y + r.z * r.z - pp;
let mut fac: f64 = b * b - c;
if fac <= 0.0 {
return Ok(false);
}
fac = fac.sqrt();
let par2: f64 = -b + fac;
if par2 <= 0.0 {
return Ok(false);
}
let mut par1: f64 = -b - fac;
par1 = if par1 > 0.0 { par1 } else { 0.0 };
let par: f64 = if b < 0.0 { -b } else { 0.0 };
let mut x1: f64 = r.x + par * e.x;
let mut x2: f64 = r.y + par * e.y;
let mut x3: f64 = r.z + par * e.z;
let mut xm: f64 = x1 - 1.0;
let mut yy: f64 = x2 * x2;
let mut rr: f64 = yy + x3 * x3;
let rs2: f64 = xm * xm + rr;
if rs2 <= 0.0 {
return Ok(true);
}
let rs1: f64 = x1 * x1 + rr;
r1 = rs1.sqrt();
r2 = rs2.sqrt();
let mut xc: f64 = x1 - x_cofm;
c = c1 / r1 + c2 / r2 + xc * xc + yy;
if c > crit {
return Ok(true);
}
let a: f64 = x1 * e.x + x2 * e.y;
b = a + x3 * e.z;
if -c1 * b / (rs1 * r1) - c2 * (b - e.x) / (rs2 * r2) + 2.0 * (a - x_cofm * e.x) > 0.0 {
p1 = par;
p2 = par2;
} else {
p1 = par;
p2 = par1;
}
let mut nstep: i32 = ((p2 - p1).abs() / step + 0.5).floor() as i32;
nstep = nstep.max(2);
let dp: f64 = (p2 - p1) / (nstep as f64);
let mut cmax: f64 = c - 1.0;
let mut i: i32 = 0;
while c > cmax && i < nstep {
i += 1;
cmax = c;
p = p1 + dp * (i as f64);
x1 = r.x + p * e.x;
x2 = r.y + p * e.y;
x3 = r.z + p * e.z;
xm = x1 - 1.0;
yy = x2 * x2;
rr = yy + x3 * x3;
r2 = (xm * xm + rr).sqrt();
if r2 <= 0.0 {
return Ok(true);
}
r1 = (x1 * x1 + rr).sqrt();
xc = x1 - x_cofm;
c = c1 / r1 + c2 / r2 + xc * xc + yy;
if c > crit {
return Ok(true);
}
}
Ok(false)
}