///|
/// Compute cosine of double-precision floating-point number `x`
///
/// # Examples
///
/// ```moonbit nocheck
/// assert_eq(cosf(-1.0), 0.5403023058681398)
/// assert_eq(cosf(0.0), 1)
/// assert_eq(cosf(1.5707963267948966), -4.371138828673793e-8)
/// assert_eq(cosf(3.141592653589793), -1)
/// assert_eq(cosf(10000), -0.9521553682590148)
/// ```
///
/// # Special Cases
///
/// 1. cosf(+-inf) = NaN
/// 2. cosf(NaN) = NaN
///
/// # Accuracy
///
/// 0 ulp.
pub fn cosf(x : Float) -> Float {
if x.is_nan() || x.is_inf() {
return @float.not_a_number
}
if x == 0.0 {
return 1.0
}
let (x, q) = trig_reduce(x, COS_SWITCHOVER)
sin_cos_core(x, q + 1)
}
///|
test "cosf" {
fn assert_cosf_ulp(input, expect) raise {
assert_float_ulp(expect, cosf(input), COS_F_MAX_ULP)
}
assert_cosf_ulp(-1, 0.5403022766113281)
assert_cosf_ulp(1, 0.5403022766113281)
assert_cosf_ulp(8, -0.1455000340938568)
assert_cosf_ulp(-8, -0.1455000340938568)
assert_cosf_ulp(0, 1)
assert_cosf_ulp(27, -0.29213881492614746)
assert_cosf_ulp(-27, -0.29213881492614746)
assert_cosf_ulp(0.125, 0.9921976923942566)
assert_cosf_ulp(-0.125, 0.9921976923942566)
assert_cosf_ulp(0.5, 0.8775825500488281)
assert_cosf_ulp(-0.5, 0.8775825500488281)
assert_cosf_ulp(1.5, 0.07073719799518585)
assert_cosf_ulp(-1.5, 0.07073719799518585)
assert_cosf_ulp(2, -0.41614681482315063)
assert_cosf_ulp(-2, -0.41614681482315063)
assert_cosf_ulp(3, -0.9899924993515015)
assert_cosf_ulp(-3, -0.9899924993515015)
assert_cosf_ulp(64, 0.39185723662376404)
assert_cosf_ulp(-64, 0.39185723662376404)
assert_cosf_ulp(1000, 0.5623790621757507)
assert_cosf_ulp(-1000, 0.5623790621757507)
assert_cosf_ulp(512, -0.9968333840370178)
assert_cosf_ulp(729, 0.9886955618858337)
assert_cosf_ulp(3511808, -0.8001007437705994)
assert_cosf_ulp(15.25, -0.8969548344612122)
assert_cosf_ulp(6859, -0.6190708875656128)
assert_cosf_ulp(68.25, 0.6486109495162964)
assert_cosf_ulp(701.625, -0.49771133065223694)
assert_cosf_ulp(@float.not_a_number, @float.not_a_number)
assert_cosf_ulp(@float.infinity, @float.not_a_number)
assert_cosf_ulp(@float.neg_infinity, @float.not_a_number)
}