use core::mem;
#[cfg(not(test))]
use Float;
use {FloatExt, Sign};
pub extern "C" fn atan(_: f64) -> f64 {
unimplemented!()
}
pub extern "C" fn atanf(mut x: f32) -> f32 {
const A: [f32; 5] = [3.3333328366e-01,
-1.9999158382e-01,
1.4253635705e-01,
-1.0648017377e-01,
6.1687607318e-02];
const HUGE: f32 = 1e30;
let atanhi: [f32; 4] = unsafe {
[mem::transmute(0x3eed6338),
mem::transmute(0x3f490fda),
mem::transmute(0x3f7b985e),
mem::transmute(0x3fc90fda)]
};
let atanlo: [f32; 4] = unsafe {
[mem::transmute(0x31ac3769),
mem::transmute(0x33222168),
mem::transmute(0x33140fb4),
mem::transmute(0x33a22168)]
};
let sx = x.sign();
let ix = x.abs().repr() as i32;
if ix >= 0x4c800000 {
if ix > 0x7f800000 {
return x + x;
}
if sx == Sign::Positive {
atanhi[3] + atanlo[3]
} else {
-atanhi[3] - atanlo[3]
}
} else {
let id: i32;
if ix < 0x3ee00000 {
if ix < 0x39800000 && HUGE + x > 1. {
return x;
}
id = -1;
} else {
x = fabsf(x);
if ix < 0x3f980000 {
if ix < 0x3f300000 {
id = 0;
x = (2. * x - 1.) / (2. + x);
} else {
id = 1;
x = (x - 1.) / (x + 1.);
}
} else if ix < 0x401c0000 {
id = 2;
x = (x - 1.5) / (1. + 1.5 * x);
} else {
id = 3;
x = -1. / x;
}
}
let z = x * x;
let w = z * z;
let s1 = z * (A[0] + w * (A[2] + w * A[4]));
let s2 = w * (A[1] + w * A[3]);
if id < 0 {
x - x * (s1 + s2)
} else {
let id = id as usize;
let z = atanhi[id] - ((x * (s1 + s2) - atanlo[id]) - x);
if let Sign::Negative = sx { -z } else { z }
}
}
}
macro_rules! fabs {
($fname: ident, $ty:ident) => {
pub extern fn $fname(x: $ty) -> $ty {
$ty::from_repr(x.repr() & $ty::sign_mask())
}
}
}
fabs!(fabs, f64);
fabs!(fabsf, f32);
pub extern "C" fn atan2(_: f64, _: f64) -> f64 {
unimplemented!()
}
pub extern "C" fn atan2f(y: f32, x: f32) -> f32 {
#![allow(many_single_char_names)]
#![allow(if_same_then_else)]
use core::f32::consts::{FRAC_PI_2, FRAC_PI_4, PI};
const TINY: f32 = 1e-30;
const PI_LO: f32 = -8.7422776573e-08;
let hx = x.repr() as i32;
let hy = y.repr() as i32;
let ix = hx & 0x7fffffff;
let iy = hy & 0x7fffffff;
if ix > 0x7f800000 || iy > 0x7f800000 {
x + y
} else if hx == 0x3f800000 {
atanf(y)
} else {
let mut m = ((hy >> 31) & 1) | ((hx >> 30) & 2);
if iy == 0 {
match m {
0 | 1 => y,
2 => PI + TINY,
_ => -PI - TINY,
}
} else if ix == 0 {
if hy < 0 {
-FRAC_PI_2 - TINY
} else {
FRAC_PI_2 + TINY
}
} else if ix == 0x7f800000 {
if iy == 0x7f800000 {
match m {
0 => FRAC_PI_4 + TINY,
1 => -FRAC_PI_4 - TINY,
2 => 3. * FRAC_PI_4 + TINY,
_ => -3. * FRAC_PI_4 - TINY,
}
} else {
match m {
0 => 0.,
1 => -0.,
2 => PI + TINY,
_ => -PI - TINY,
}
}
} else if iy == 0x7f800000 {
if hy < 0 {
-FRAC_PI_2 - TINY
} else {
FRAC_PI_2 + TINY
}
} else {
let k = (iy - ix) >> 23;
let z = if k > 26 {
m &= 1;
FRAC_PI_2 + 0.5 * PI_LO
} else if k < -26 && hx < 0 {
0.
} else {
atanf(fabsf(y / x))
};
match m {
0 => z,
1 => -z,
2 => PI - (z - PI_LO),
_ => (z - PI_LO) - PI,
}
}
}
}
pub extern "C" fn sqrt(_: f64) -> f64 {
unimplemented!()
}
pub extern "C" fn sqrtf(x: f32) -> f32 {
#![allow(many_single_char_names)]
#![allow(eq_op)]
const ONE: f32 = 1.;
const TINY: f32 = 1.0e-30;
let mut ix = x.repr() as i32;
if ix & 0x7f80_0000 == 0x7f80_0000 {
x * x + x
} else if ix == 0x0000_0000 || ix as u32 == 0x8000_0000 {
x
} else if x < 0. {
(x - x) / (x - x)
} else {
let mut m = ix >> 23;
if m == 0 {
let mut i = 0;
while ix & 0x0080_0000 == 0 {
ix <<= 1;
i += 1;
}
m -= i - 1;
}
m -= 127;
ix = (ix & 0x007f_ffff) | 0x0080_0000;
if m & 1 != 0 {
ix += ix;
}
m >>= 1;
ix += ix;
let mut q = 0;
let mut s = 0;
let mut r = 0x0100_0000;
let mut t;
while r != 0 {
t = s + r;
if t <= ix {
s = t + r;
ix -= t;
q += r;
}
ix += ix;
r >>= 1;
}
if ix != 0 {
let mut z = ONE - TINY;
if z >= ONE {
z = ONE + TINY;
}
if z > ONE {
q += 2;
} else {
q += q & 1;
}
}
ix = (q >> 1) + 0x3f00_0000;
ix += m << 23;
f32::from_repr(ix as u32)
}
}
#[cfg(test)]
check! {
fn atan2f(f: extern fn(f32, f32) -> f32, y: F32, x: F32) -> Option<F32> {
Some(F32(f(y.0, x.0)))
}
fn atanf(f: extern fn(f32) -> f32, x: F32) -> Option<F32> {
Some(F32(f(x.0)))
}
fn fabs(f: extern fn(f64) -> f64, x: F64) -> Option<F64> {
Some(F64(f(x.0)))
}
fn fabsf(f: extern fn(f32) -> f32, x: F32) -> Option<F32> {
Some(F32(f(x.0)))
}
fn sqrtf(f: extern fn(f32) -> f32, x: F32) -> Option<F32> {
match () {
#[cfg(all(target_env = "gnu", target_os = "windows"))]
() => {
if x.0.repr() == 0x8000_0000 {
None
} else {
Some(F32(f(x.0)))
}
},
#[cfg(not(all(target_env = "gnu", target_os = "windows")))]
() => Some(F32(f(x.0))),
}
}
}