use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
use crate::float::arithmetic::cos::{
reduce_huge, signed_constant, sin_bound, trig_near_zero_bracket,
trig_rational_near_zero_bracket, trig_turns_near_zero_bracket,
};
use crate::float::arithmetic::round_near_x::{
round_near_reciprocal, round_rational_reciprocal_leading_term,
};
use crate::float::arithmetic::sin_cos::{
sin_cos_rational_helper, sin_cos_turns_helper, sin_cos_with_period_prec_round_normal_ref,
};
use crate::float::arithmetic::tan::{
MAX_CANCEL, MAX_SETTLED_EXPONENT, MIN_SETTLED_EXPONENT, nearest_bracket, round_bracket_signed,
round_bracket_signed_by,
};
use crate::float::conversion::string::set_str::overflow;
use crate::{Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
use core::cmp::Ordering::{self, Equal};
use core::cmp::max;
use malachite_base::num::arithmetic::traits::{
Abs, AddMul, CeilingLogBase2, Cot, CotAssign, IsPowerOf2, Mod, Parity, Pow, Reciprocal, Square,
};
use malachite_base::num::basic::floats::PrimitiveFloat;
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::{
Infinity as InfinityTrait, NaN as NaNTrait, NegativeInfinity,
NegativeZero as NegativeZeroTrait, One, Zero as ZeroTrait,
};
use malachite_base::num::comparison::traits::PartialOrdAbs;
use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
use malachite_base::num::logic::traits::SignificantBits;
use malachite_base::rounding_modes::RoundingMode::{self, *};
use malachite_nz::integer::Integer;
use malachite_nz::natural::arithmetic::float::round::float_can_round;
use malachite_nz::platform::Limb;
use malachite_q::Rational;
fn cot_bracket(
x: &Float,
s: &Float,
c: &Float,
m: u64,
prec: u64,
rm: RoundingMode,
) -> Option<(Float, Ordering)> {
let negative = s.is_sign_negative() != c.is_sign_negative();
if *s == 0u32
|| (s.get_exponent() == Some(Float::MIN_EXPONENT)
&& s.significand_ref().unwrap().is_power_of_2())
{
return Some(overflow(!negative, prec, rm));
}
let (s_lo, s_hi) = nearest_bracket(s, m);
let (c_lo, c_hi) = if *c == 0u32 {
let (lo, hi) = trig_near_zero_bracket(x, m + 64, MAX_CANCEL, true);
if lo < 0u32 { (-hi, -lo) } else { (lo, hi) }
} else {
nearest_bracket(c, m)
};
round_bracket_signed_by(negative, c_lo / s_hi, c_hi / s_lo, prec, rm)
}
fn cot_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
assert_ne!(rm, Exact, "Inexact cot");
let exp_x = i64::from(x.get_exponent().unwrap());
let n = i64::exact_from(max(x.get_prec().unwrap(), prec));
if exp_x < -(n << 1) {
return round_near_reciprocal(x, false, prec, rm);
}
let mut m = prec + prec.ceiling_log_base_2() + 13;
let mut increment = Limb::WIDTH;
loop {
let (s, c, _, _) = x.sin_cos_prec_ref(m);
let q = if s == 0u32 || c == 0u32 {
None
} else {
Some(c.div_prec_ref_ref(&s, m).0)
};
match q.as_ref().and_then(Float::get_exponent).map(i64::from) {
Some(e) if e > MIN_SETTLED_EXPONENT && e < MAX_SETTLED_EXPONENT => {
let q = q.unwrap();
if float_can_round(q.significand_ref().unwrap(), m - 2, prec, rm) {
return Float::from_float_prec_round(q, prec, rm);
}
}
_ => {
if let Some(result) = cot_bracket(x, &s, &c, m, prec, rm) {
return result;
}
}
}
m += increment;
increment = m >> 1;
}
}
fn cot_rational_tiny(
x: &Rational,
ax: &Rational,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
let x2 = ax.square();
let mut w = prec + 64;
let mut terms = 2u64;
loop {
let s_lo = sin_bound(ax, w, false);
let s_hi = sin_bound(ax, w, true);
let mut c_lo = Rational::ONE;
let mut term = Rational::ONE;
let mut c_hi = Rational::ONE;
for k in 1..=terms {
term *= &x2;
term /= Rational::from((k << 1) * ((k << 1) - 1));
if k.odd() {
c_lo = &c_hi - &term;
} else {
c_hi = &c_lo + &term;
}
}
let lo = c_lo / s_hi;
let hi = c_hi / s_lo;
if let Some(result) = round_bracket_signed(x, lo, hi, prec, rm) {
return result;
}
w <<= 1;
terms += 1;
}
}
fn cot_rational_bracket(
x: &Rational,
exp_x: i64,
s: &Float,
c: &Float,
m: u64,
prec: u64,
rm: RoundingMode,
) -> Option<(Float, Ordering)> {
let negative = s.is_sign_negative() != c.is_sign_negative();
if *s == 0u32
|| (s.get_exponent() == Some(Float::MIN_EXPONENT)
&& s.significand_ref().unwrap().is_power_of_2())
{
return Some(overflow(!negative, prec, rm));
}
let (s_lo, s_hi) = nearest_bracket(s, m);
let (c_lo, c_hi) = if *c == 0u32 {
let w = m + 64;
let reduced;
let (y, extra) = if exp_x >= Float::MAX_EXPONENT_I64 {
reduced = reduce_huge(x, exp_x, w);
(&reduced, Some(2 - i64::exact_from(w)))
} else {
(x, None)
};
let exp_y = y.floor_log_base_2_abs() + 1;
let (lo, hi) = trig_rational_near_zero_bracket(y, exp_y, extra, w, m, true);
if lo < 0u32 { (-hi, -lo) } else { (lo, hi) }
} else {
nearest_bracket(c, m)
};
round_bracket_signed_by(negative, c_lo / s_hi, c_hi / s_lo, prec, rm)
}
pub(crate) fn cot_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
assert_ne!(rm, Exact, "Inexact cot");
let exp_x = x.floor_log_base_2_abs() + 1; if let Some(result) = round_rational_reciprocal_leading_term(x, exp_x, false, prec, rm) {
return result;
}
if exp_x < 0 && -(exp_x << 2) > i64::exact_from(prec) + 3 {
let ax = x.abs();
let ax3 = (&ax).pow(3u64);
let t_lo = &ax + &ax3 / const { Rational::const_from_unsigned(3) };
let t_hi = (&t_lo).add_mul(&ax3, &(&ax).square());
if let Some(result) =
round_bracket_signed(x, t_hi.reciprocal(), t_lo.reciprocal(), prec, rm)
{
return result;
}
return cot_rational_tiny(x, &ax, prec, rm);
}
let mut m = prec + prec.ceiling_log_base_2() + 13;
let mut increment = Limb::WIDTH;
loop {
let (s, c, _, _) = sin_cos_rational_helper(x, m, Nearest);
let q = if s == 0u32 || c == 0u32 {
None
} else {
Some(c.div_prec_ref_ref(&s, m).0)
};
match q.as_ref().and_then(Float::get_exponent).map(i64::from) {
Some(e) if e > MIN_SETTLED_EXPONENT && e < MAX_SETTLED_EXPONENT => {
let q = q.unwrap();
if float_can_round(q.significand_ref().unwrap(), m - 2, prec, rm) {
return Float::from_float_prec_round(q, prec, rm);
}
}
_ => {
if let Some(result) = cot_rational_bracket(x, exp_x, &s, &c, m, prec, rm) {
return result;
}
}
}
m += increment;
increment = m >> 1;
}
}
fn cot_turns_special_case(q: &Rational, prec: u64, rm: RoundingMode) -> Option<(Float, Ordering)> {
let d = q.denominator_ref();
if *d > 12u32 {
return None;
}
let d = u64::exact_from(d);
let negative = *q < 0u32;
let n = u64::exact_from(
&Integer::from_sign_and_abs_ref(!negative, q.numerator_ref()).mod_op(Integer::from(d)),
);
match d {
2 | 4 | 8 => Some(match n * (8 / d) {
4 => (
if negative {
Float::INFINITY
} else {
Float::NEGATIVE_INFINITY
},
Equal,
),
2 => (Float::ZERO, Equal),
6 => (Float::NEGATIVE_ZERO, Equal),
1 | 5 => (Float::one_prec(prec), Equal),
_ => (-Float::one_prec(prec), Equal),
}),
_ if rm == Exact => None,
3 | 6 | 12 => Some(match n * (12 / d) {
1 | 7 => signed_constant(Float::sqrt_3_prec_round, false, prec, rm),
5 | 11 => signed_constant(Float::sqrt_3_prec_round, true, prec, rm),
2 | 8 => signed_constant(Float::sqrt_3_over_3_prec_round, false, prec, rm),
_ => signed_constant(Float::sqrt_3_over_3_prec_round, true, prec, rm),
}),
_ => None,
}
}
fn cot_turns_bracket<F: Fn() -> Rational>(
q: F,
s: &Float,
c: &Float,
m: u64,
prec: u64,
rm: RoundingMode,
) -> Option<(Float, Ordering)> {
let negative = s.is_sign_negative() != c.is_sign_negative();
if *s == 0u32
|| (s.get_exponent() == Some(Float::MIN_EXPONENT)
&& s.significand_ref().unwrap().is_power_of_2())
{
return Some(overflow(!negative, prec, rm));
}
let (s_lo, s_hi) = nearest_bracket(s, m);
let (c_lo, c_hi) = if *c == 0u32 {
let (lo, hi) = trig_turns_near_zero_bracket(&q(), m, true)?;
if lo < 0u32 { (-hi, -lo) } else { (lo, hi) }
} else {
nearest_bracket(c, m)
};
round_bracket_signed_by(negative, c_lo / s_hi, c_hi / s_lo, prec, rm)
}
fn cot_turns_helper(q: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
let exp_q = q.floor_log_base_2_abs() + 1;
if exp_q >= -4
&& let Some(result) = cot_turns_special_case(q, prec, rm)
{
return result;
}
assert_ne!(rm, Exact, "Inexact cot_with_period");
let mut m = prec + prec.ceiling_log_base_2() + 13;
let mut increment = Limb::WIDTH;
loop {
let (s, c, _, _) = sin_cos_turns_helper(q, m, Nearest);
let t = if s == 0u32 || c == 0u32 {
None
} else {
Some(c.div_prec_ref_ref(&s, m).0)
};
match t.as_ref().and_then(Float::get_exponent).map(i64::from) {
Some(e) if e > MIN_SETTLED_EXPONENT && e < MAX_SETTLED_EXPONENT => {
let t = t.unwrap();
if float_can_round(t.significand_ref().unwrap(), m - 2, prec, rm) {
return Float::from_float_prec_round(t, prec, rm);
}
}
_ => {
if let Some(result) = cot_turns_bracket(|| q.clone(), &s, &c, m, prec, rm) {
return result;
}
}
}
m += increment;
increment = m >> 1;
}
}
fn cot_with_period_prec_round_normal_ref(
x: &Float,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
let xr;
let xp = if x.lt_abs(&u) {
x
} else {
let p = i64::exact_from(x.get_prec().unwrap()) - i64::from(x.get_exponent().unwrap());
let (r, o) =
x.rem_unsigned_prec_round_ref(u, u64::WIDTH + u64::exact_from(max(p, 0)), Exact);
assert_eq!(o, Equal);
if r == 0u32 {
return (
if *x < 0u32 {
Float::NEGATIVE_INFINITY
} else {
Float::INFINITY
},
Equal,
);
}
xr = r;
&xr
};
let exp_x = i64::from(xp.get_exponent().unwrap());
if exp_x >= i64::exact_from(u.significant_bits()) - 4
&& let Some(result) =
cot_turns_special_case(&(Rational::exact_from(xp) / Rational::from(u)), prec, rm)
{
return result;
}
assert_ne!(rm, Exact, "Inexact cot_with_period");
let mut m = prec + prec.ceiling_log_base_2() + 13;
let mut increment = Limb::WIDTH;
loop {
let (s, c, _, _) = sin_cos_with_period_prec_round_normal_ref(xp, u, m, Nearest);
let q = if s == 0u32 || c == 0u32 {
None
} else {
Some(c.div_prec_ref_ref(&s, m).0)
};
match q.as_ref().and_then(Float::get_exponent).map(i64::from) {
Some(e) if e > MIN_SETTLED_EXPONENT && e < MAX_SETTLED_EXPONENT => {
let q = q.unwrap();
if float_can_round(q.significand_ref().unwrap(), m - 2, prec, rm) {
return Float::from_float_prec_round(q, prec, rm);
}
}
_ => {
if let Some(result) = cot_turns_bracket(
|| Rational::exact_from(xp) / Rational::from(u),
&s,
&c,
m,
prec,
rm,
) {
return result;
}
}
}
m += increment;
increment = m >> 1;
}
}
impl Float {
#[inline]
pub fn cot_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
self.cot_prec_round_ref(prec, rm)
}
pub fn cot_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
assert_ne!(prec, 0);
match &self.0 {
NaN | Infinity { .. } => (Self::NAN, Equal),
Zero { .. } => (
if self.is_sign_negative() {
Self::NEGATIVE_INFINITY
} else {
Self::INFINITY
},
Equal,
),
Finite { .. } => cot_prec_round_normal_ref(self, prec, rm),
}
}
#[inline]
pub fn cot_prec(self, prec: u64) -> (Self, Ordering) {
self.cot_prec_round(prec, Nearest)
}
#[inline]
pub fn cot_prec_ref(&self, prec: u64) -> (Self, Ordering) {
self.cot_prec_round_ref(prec, Nearest)
}
#[inline]
pub fn cot_round(self, rm: RoundingMode) -> (Self, Ordering) {
let prec = self.significant_bits();
self.cot_prec_round(prec, rm)
}
#[inline]
pub fn cot_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
self.cot_prec_round_ref(self.significant_bits(), rm)
}
#[inline]
pub fn cot_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
let o;
(*self, o) = self.cot_prec_round_ref(prec, rm);
o
}
#[inline]
pub fn cot_prec_assign(&mut self, prec: u64) -> Ordering {
self.cot_prec_round_assign(prec, Nearest)
}
#[inline]
pub fn cot_round_assign(&mut self, rm: RoundingMode) -> Ordering {
let prec = self.significant_bits();
self.cot_prec_round_assign(prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn cot_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
Self::cot_rational_prec_round_ref(&x, prec, rm)
}
pub fn cot_rational_prec_round_ref(
x: &Rational,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
assert_ne!(prec, 0);
if *x == 0u32 {
return (Self::INFINITY, Equal);
}
cot_rational_helper(x, prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn cot_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
Self::cot_rational_prec_round_ref(&x, prec, Nearest)
}
#[inline]
pub fn cot_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
Self::cot_rational_prec_round_ref(x, prec, Nearest)
}
#[inline]
pub fn cot_with_period_prec_round(
self,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
self.cot_with_period_prec_round_ref(u, prec, rm)
}
pub fn cot_with_period_prec_round_ref(
&self,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
assert_ne!(prec, 0);
match &self.0 {
_ if u == 0 => (Self::NAN, Equal),
NaN | Infinity { .. } => (Self::NAN, Equal),
Zero { .. } => (
if self.is_sign_negative() {
Self::NEGATIVE_INFINITY
} else {
Self::INFINITY
},
Equal,
),
Finite { .. } => cot_with_period_prec_round_normal_ref(self, u, prec, rm),
}
}
#[inline]
pub fn cot_with_period_prec(self, u: u64, prec: u64) -> (Self, Ordering) {
self.cot_with_period_prec_round(u, prec, Nearest)
}
#[inline]
pub fn cot_with_period_prec_ref(&self, u: u64, prec: u64) -> (Self, Ordering) {
self.cot_with_period_prec_round_ref(u, prec, Nearest)
}
#[inline]
pub fn cot_with_period_round(self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
let prec = self.significant_bits();
self.cot_with_period_prec_round(u, prec, rm)
}
#[inline]
pub fn cot_with_period_round_ref(&self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
self.cot_with_period_prec_round_ref(u, self.significant_bits(), rm)
}
#[inline]
pub fn cot_with_period(self, u: u64) -> Self {
let prec = self.significant_bits();
self.cot_with_period_prec(u, prec).0
}
#[inline]
pub fn cot_with_period_ref(&self, u: u64) -> Self {
self.cot_with_period_prec_ref(u, self.significant_bits()).0
}
#[inline]
pub fn cot_with_period_prec_round_assign(
&mut self,
u: u64,
prec: u64,
rm: RoundingMode,
) -> Ordering {
let (t, o) = self.cot_with_period_prec_round_ref(u, prec, rm);
*self = t;
o
}
#[inline]
pub fn cot_with_period_prec_assign(&mut self, u: u64, prec: u64) -> Ordering {
self.cot_with_period_prec_round_assign(u, prec, Nearest)
}
#[inline]
pub fn cot_with_period_round_assign(&mut self, u: u64, rm: RoundingMode) -> Ordering {
let prec = self.significant_bits();
self.cot_with_period_prec_round_assign(u, prec, rm)
}
#[inline]
pub fn cot_with_period_assign(&mut self, u: u64) {
let prec = self.significant_bits();
self.cot_with_period_prec_assign(u, prec);
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn cot_with_period_rational_prec_round(
x: Rational,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_round_ref(&x, u, prec, rm)
}
pub fn cot_with_period_rational_prec_round_ref(
x: &Rational,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
assert_ne!(prec, 0);
if u == 0 {
return (Self::NAN, Equal);
}
if *x == 0u32 {
return (Self::INFINITY, Equal);
}
let q = x / Rational::from(u) % Rational::ONE;
if q == 0u32 {
return (
if *x < 0u32 {
Self::NEGATIVE_INFINITY
} else {
Self::INFINITY
},
Equal,
);
}
cot_turns_helper(&q, prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn cot_with_period_rational_prec(x: Rational, u: u64, prec: u64) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_round_ref(&x, u, prec, Nearest)
}
#[inline]
pub fn cot_with_period_rational_prec_ref(x: &Rational, u: u64, prec: u64) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_round_ref(x, u, prec, Nearest)
}
#[inline]
pub fn cot_pi_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
self.cot_with_period_prec_round(2, prec, rm)
}
#[inline]
pub fn cot_pi_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
self.cot_with_period_prec_round_ref(2, prec, rm)
}
#[inline]
pub fn cot_pi_prec(self, prec: u64) -> (Self, Ordering) {
self.cot_with_period_prec(2, prec)
}
#[inline]
pub fn cot_pi_prec_ref(&self, prec: u64) -> (Self, Ordering) {
self.cot_with_period_prec_ref(2, prec)
}
#[inline]
pub fn cot_pi_round(self, rm: RoundingMode) -> (Self, Ordering) {
self.cot_with_period_round(2, rm)
}
#[inline]
pub fn cot_pi_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
self.cot_with_period_round_ref(2, rm)
}
#[inline]
pub fn cot_pi(self) -> Self {
let prec = self.significant_bits();
self.cot_pi_prec(prec).0
}
#[inline]
pub fn cot_pi_ref(&self) -> Self {
self.cot_pi_prec_ref(self.significant_bits()).0
}
#[inline]
pub fn cot_pi_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
self.cot_with_period_prec_round_assign(2, prec, rm)
}
#[inline]
pub fn cot_pi_prec_assign(&mut self, prec: u64) -> Ordering {
self.cot_with_period_prec_assign(2, prec)
}
#[inline]
pub fn cot_pi_round_assign(&mut self, rm: RoundingMode) -> Ordering {
self.cot_with_period_round_assign(2, rm)
}
#[inline]
pub fn cot_pi_assign(&mut self) {
let prec = self.significant_bits();
self.cot_pi_prec_assign(prec);
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn cot_pi_rational_prec_round(
x: Rational,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_round_ref(&x, 2, prec, rm)
}
#[inline]
pub fn cot_pi_rational_prec_round_ref(
x: &Rational,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_round_ref(x, 2, prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn cot_pi_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_ref(&x, 2, prec)
}
#[inline]
pub fn cot_pi_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
Self::cot_with_period_rational_prec_ref(x, 2, prec)
}
}
impl Cot for Float {
type Output = Self;
#[inline]
fn cot(self) -> Self {
let prec = self.significant_bits();
self.cot_prec_round(prec, Nearest).0
}
}
impl Cot for &Float {
type Output = Float;
#[inline]
fn cot(self) -> Float {
self.cot_prec_round_ref(self.significant_bits(), Nearest).0
}
}
impl CotAssign for Float {
#[inline]
fn cot_assign(&mut self) {
let prec = self.significant_bits();
self.cot_prec_round_assign(prec, Nearest);
}
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_cot<T: PrimitiveFloat>(x: T) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
emulate_float_to_float_fn(Float::cot_prec, x)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_cot_rational<T: PrimitiveFloat>(x: &Rational) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
emulate_rational_to_float_fn(Float::cot_rational_prec_ref, x)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_cot_with_period<T: PrimitiveFloat>(x: T, u: u64) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
emulate_float_to_float_fn(|x, prec| Float::cot_with_period_prec(x, u, prec), x)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_cot_with_period_rational<T: PrimitiveFloat>(x: &Rational, u: u64) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
emulate_rational_to_float_fn(
|x, prec| Float::cot_with_period_rational_prec_ref(x, u, prec),
x,
)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_cot_pi<T: PrimitiveFloat>(x: T) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_cot_with_period(x, 2)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_cot_pi_rational<T: PrimitiveFloat>(x: &Rational) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_cot_with_period_rational(x, 2)
}