use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
use crate::float::arithmetic::cos::{
NEAR_ZERO_MIN_CANCEL, TrigStep, half_constant, phi_minus_1_prec_round, reduce_huge,
round_bracket, sin_bound, trig_near_zero, trig_rational_near_zero, trig_turns_near_zero,
};
use crate::float::arithmetic::round_near_x::float_round_near_x;
use crate::float::arithmetic::sin_cos::{SINCOS_THRESHOLD, sin_cos_fast};
use crate::{Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
use core::cmp::Ordering::{self, Equal, Greater, Less};
use core::cmp::{max, min};
use malachite_base::fail_on_untested_path;
use malachite_base::num::arithmetic::traits::{
Abs, CeilingLogBase2, Mod, NegAssign, PowerOf2, Sin, SinAssign,
};
use malachite_base::num::basic::floats::PrimitiveFloat;
use malachite_base::num::basic::integers::PrimitiveInt;
use malachite_base::num::basic::traits::{
NaN as NaNTrait, 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 sin_ziv_step(
x: &Float,
exp_x: i64,
prec: u64,
rm: RoundingMode,
reduce: bool,
m: &mut u64,
) -> TrigStep {
let near_zero_threshold = max(NEAR_ZERO_MIN_CANCEL, prec >> 4);
let xr;
let xx = if reduce {
let c_prec = u64::exact_from(exp_x) + *m - 1;
let pi = Float::pi_prec(c_prec).0;
xr = x.ieee_remainder_prec_ref_val(&pi << 1u32, *m).0;
let c = pi.sub_prec_round((&xr).abs(), c_prec, Down).0;
let threshold = 3 - i64::exact_from(*m);
if xr == 0u32
|| i64::from(xr.get_exponent().unwrap()) < threshold
|| c == 0u32
|| i64::from(c.get_exponent().unwrap()) < threshold
{
let cancel = *m - 4;
return if cancel >= near_zero_threshold {
TrigStep::NearZero(cancel)
} else {
TrigStep::Retry
};
}
&xr
} else {
x
};
let sign = *xx < 0u32;
let c = xx
.cos_prec_round_ref(*m, Up)
.0
.square_prec_round(*m, Ceiling)
.0;
let mut c = Float::ONE
.sub_prec_round(c, *m, Down)
.0
.sqrt_prec_round(*m, Down)
.0;
if sign {
c.neg_assign();
}
if c == 0u32 {
let cancel = (*m >> 1).saturating_sub(3);
if reduce && cancel >= near_zero_threshold {
return TrigStep::NearZero(cancel);
}
*m = max(*m, x.significant_bits()) << 1;
return TrigStep::Retry;
}
let exp_c = i64::from(c.get_exponent().unwrap());
let err = (exp_c << 1) + i64::exact_from(*m) - 3 - i64::from(reduce);
if err > 0 && float_can_round(c.significand_ref().unwrap(), u64::exact_from(err), prec, rm) {
return TrigStep::Done(c);
}
let bound_exp = max(exp_c, 4 - i64::exact_from(*m) - exp_c) + 1;
if reduce && bound_exp < 0 {
let cancel = u64::exact_from(-bound_exp);
if cancel >= near_zero_threshold {
return TrigStep::NearZero(cancel);
}
}
if err < i64::exact_from(prec) {
*m += u64::exact_from(i64::exact_from(prec) - err);
}
assert_ne!(exp_c, 1);
TrigStep::Retry
}
fn sin_rational_series(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
let mut w = prec + 10;
let mut increment = Limb::WIDTH;
loop {
let lo = sin_bound(x, w, false);
let hi = sin_bound(x, w, true);
if let Some(result) = round_bracket(&lo, &hi, prec, rm) {
return result;
}
w += increment;
increment = w >> 1;
}
}
pub(crate) fn sin_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
assert_ne!(rm, Exact, "Inexact sin");
let exp_x = x.floor_log_base_2_abs() + 1; if exp_x < UNDERFLOW_EXPONENT {
return underflowed(*x > 0u32, prec, rm);
}
if exp_x < 0 && u64::exact_from(-exp_x) << 4 >= prec + 10 {
return sin_rational_series(x, prec, rm);
}
let huge = exp_x >= Float::MAX_EXPONENT_I64;
let mut w = prec + 10;
let mut increment = Limb::WIDTH;
loop {
let reduced;
let (y, extra) = if huge {
reduced = reduce_huge(x, exp_x, w);
(&reduced, Some(2 - i64::exact_from(w)))
} else {
(x, None)
};
if *y == 0u32 {
fail_on_untested_path("sin_rational_helper, reduced argument is zero");
} else {
let (y_f, y_o) = Float::from_rational_prec_ref(y, w);
if !huge && y_o == Equal {
return sin_prec_round_normal_ref(&y_f, prec, rm);
}
let s_f = (&y_f).sin();
let exp_y = y.floor_log_base_2_abs() + 1;
let exp_s = s_f
.get_exponent()
.map_or(Float::MIN_EXPONENT_I64, i64::from);
if exp_s < 0 {
let cancel = u64::exact_from(-exp_s);
if cancel >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4) {
return trig_rational_near_zero(y, exp_y, prec, rm, extra, w, false);
}
}
let w_i = i64::exact_from(w);
let mut delta = Rational::power_of_2(exp_s - w_i) + Rational::power_of_2(exp_y - w_i);
if let Some(extra) = extra {
delta += Rational::power_of_2(extra);
}
let s = Rational::exact_from(&s_f);
if let Some(result) = round_bracket(&(&s - &delta), &(s + delta), prec, rm) {
return result;
}
}
w += increment;
increment = w >> 1;
}
}
pub(crate) const UNDERFLOW_EXPONENT: i64 = Float::MIN_EXPONENT_I64 - 1;
pub(crate) const TINY_UNDERFLOW_EXPONENT: i64 = UNDERFLOW_EXPONENT - 1;
pub(crate) fn underflowed(positive: bool, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
let away = match rm {
Ceiling => positive,
Floor => !positive,
Up => true,
_ => false,
};
let min_positive = Float::min_positive_value_prec(prec);
match (positive, away) {
(true, true) => (min_positive, Greater),
(true, false) => (Float::ZERO, Less),
(false, true) => (-min_positive, Less),
(false, false) => (Float::NEGATIVE_ZERO, Greater),
}
}
pub(crate) const SCALE: u64 = 64;
pub(crate) const SCALE_I64: i64 = SCALE as i64;
const MIN_SCALED_EXPONENT: i64 = Float::MIN_EXPONENT_I64 + SCALE_I64;
pub(crate) const SCALED_INPUT_EXPONENT: i64 = Float::MIN_EXPONENT_I64 + 66;
pub(crate) fn scaled_underflow(
t: &Float,
positive: bool,
prec: u64,
rm: RoundingMode,
) -> Option<(Float, Ordering)> {
let exp_t = match t.get_exponent() {
Some(e) => i64::from(e),
None => const { MIN_SCALED_EXPONENT - 2 },
};
if exp_t >= MIN_SCALED_EXPONENT {
return None;
}
let away = match rm {
Ceiling => positive,
Floor => !positive,
Up => true,
Nearest => exp_t == const { MIN_SCALED_EXPONENT - 1 },
_ => false,
};
let min_positive = Float::min_positive_value_prec(prec);
Some(match (positive, away) {
(true, true) => (min_positive, Greater),
(true, false) => (Float::ZERO, Less),
(false, true) => (-min_positive, Less),
(false, false) => (Float::NEGATIVE_ZERO, Greater),
})
}
pub(crate) fn sin_turns_special_case(
q: &Rational,
prec: u64,
rm: RoundingMode,
) -> Option<(Float, Ordering)> {
let d = q.denominator_ref();
if *d > 20u32 {
return None;
}
let d = u64::exact_from(d);
let n = u64::exact_from(
&Integer::from_sign_and_abs_ref(*q >= 0u32, q.numerator_ref()).mod_op(Integer::from(d)),
);
let negative = n > d >> 1;
match d {
1 | 2 => Some((
if *q < 0u32 {
Float::NEGATIVE_ZERO
} else {
Float::ZERO
},
Equal,
)),
4 => Some((
if negative {
-Float::one_prec(prec)
} else {
Float::one_prec(prec)
},
Equal,
)),
12 => Some((
if negative {
-(Float::one_prec(prec) >> 1u32)
} else {
Float::one_prec(prec) >> 1u32
},
Equal,
)),
_ if rm == Exact => None,
3 | 6 => Some(half_constant(
|prec, rm| const { Float::const_from_unsigned(3) }.sqrt_prec_round(prec, rm),
negative,
prec,
rm,
)),
8 => Some(half_constant(Float::sqrt_2_prec_round, negative, prec, rm)),
20 => Some(if n == 1 || n == 9 || n == 11 || n == 19 {
half_constant(phi_minus_1_prec_round, negative, prec, rm)
} else {
half_constant(Float::phi_prec_round, negative, prec, rm)
}),
_ => None,
}
}
pub(crate) fn sin_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_ZERO
} else {
Float::ZERO
},
Equal,
);
}
xr = r;
&xr
};
let exp_x = i64::from(xp.get_exponent().unwrap());
let u_bits = i64::exact_from(u.significant_bits());
if exp_x >= u_bits - 5
&& let Some(result) =
sin_turns_special_case(&(Rational::exact_from(xp) / Rational::from(u)), prec, rm)
{
return result;
}
assert_ne!(rm, Exact, "Inexact sin_with_period");
let mut prec_t =
prec + u64::exact_from(max(exp_x, i64::exact_from(prec.ceiling_log_base_2()))) + 8;
let mut increment = Limb::WIDTH;
let u_float = Float::from(u);
let scaled = exp_x <= SCALED_INPUT_EXPONENT;
let xs;
let xp_scaled = if scaled {
xs = xp << SCALE;
&xs
} else {
xp
};
loop {
let mut t = Float::pi_prec(prec_t).0 << 1u32;
t.mul_prec_assign_ref(xp_scaled, prec_t);
t.div_prec_assign_ref(&u_float, prec_t);
if scaled {
if let Some(result) = scaled_underflow(&t, *xp > 0u32, prec, rm) {
return result;
}
t >>= SCALE;
}
let exp_t = i64::from(t.get_exponent().unwrap());
let prec_t_i = i64::exact_from(prec_t);
let mut err = exp_t + 2 - prec_t_i;
t.sin_prec_round_assign(prec_t, Up);
let exp_t = i64::from(t.get_exponent().unwrap());
if exp_t < 0 && exp_x >= u_bits - 2 {
let cancel = u64::exact_from(-exp_t);
if cancel >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4)
&& let Some(result) = trig_turns_near_zero(
&(Rational::exact_from(xp) / Rational::from(u)),
prec,
rm,
false,
)
{
return result;
}
}
err = if err <= exp_t - prec_t_i {
exp_t - prec_t_i + 1
} else {
err + 1
};
err = exp_t - err;
if err > 0 && float_can_round(t.significand_ref().unwrap(), u64::exact_from(err), prec, rm)
{
return Float::from_float_prec_round(t, prec, rm);
}
prec_t += increment;
increment = prec_t >> 1;
}
}
pub(crate) fn sin_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) = sin_turns_special_case(q, prec, rm)
{
return result;
}
assert_ne!(rm, Exact, "Inexact sin_with_period");
let mut w = prec + prec.ceiling_log_base_2() + 8;
let mut increment = Limb::WIDTH;
let scaled = exp_q <= SCALED_INPUT_EXPONENT;
let qs;
let q_scaled = if scaled {
qs = q << SCALE;
&qs
} else {
q
};
loop {
let mut t = Float::pi_prec(w).0 << 1u32;
t.mul_prec_assign(Float::from_rational_prec_ref(q_scaled, w).0, w);
if scaled {
if let Some(result) = scaled_underflow(&t, *q > 0u32, prec, rm) {
return result;
}
t >>= SCALE;
}
let exp_t = i64::from(t.get_exponent().unwrap());
let w_i = i64::exact_from(w);
let mut err = exp_t + 2 - w_i;
t.sin_prec_round_assign(w, Up);
let exp_t = i64::from(t.get_exponent().unwrap());
if exp_t < 0 && exp_q >= -2 {
let cancel = u64::exact_from(-exp_t);
if cancel >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4)
&& let Some(result) = trig_turns_near_zero(q, prec, rm, false)
{
return result;
}
}
err = if err <= exp_t - w_i {
exp_t - w_i + 1
} else {
err + 1
};
err = exp_t - err;
if err > 0 && float_can_round(t.significand_ref().unwrap(), u64::exact_from(err), prec, rm)
{
return Float::from_float_prec_round(t, prec, rm);
}
w += increment;
increment = w >> 1;
}
}
fn sin_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
assert_ne!(rm, Exact, "Inexact sin");
let exp_x = i64::from(x.get_exponent().unwrap());
let err1 = -(exp_x << 1);
if err1 > 0 {
let err = u64::exact_from(err1) + 2;
if err > prec + 1 {
if let Some(result) = float_round_near_x(x, min(err, prec + 2), false, prec, rm) {
return result;
}
}
}
if prec >= SINCOS_THRESHOLD {
return sin_cos_fast(x, prec, rm, true, false).0.unwrap();
}
sin_basic(x, exp_x, err1, prec, rm)
}
pub(crate) fn sin_basic(
x: &Float,
exp_x: i64,
err1: i64,
prec: u64,
rm: RoundingMode,
) -> (Float, Ordering) {
let mut m = prec + max(prec, u64::try_from(exp_x).unwrap_or(0)).ceiling_log_base_2() + 8;
if exp_x < 0 {
m += u64::exact_from(err1);
}
let reduce = exp_x > 2 || (exp_x == 2 && x.ge_abs(&3u32));
let mut increment = Limb::WIDTH;
let c = loop {
match sin_ziv_step(x, exp_x, prec, rm, reduce, &mut m) {
TrigStep::Done(c) => break c,
TrigStep::NearZero(cancel) => return trig_near_zero(x, prec, rm, cancel, false),
TrigStep::Retry => {}
}
m += increment;
increment = m >> 1;
};
Float::from_float_prec_round(c, prec, rm)
}
impl Float {
#[inline]
pub fn sin_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
self.sin_prec_round_ref(prec, rm)
}
pub fn sin_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
assert_ne!(prec, 0);
match &self.0 {
NaN | Infinity { .. } => (Self::NAN, Equal),
Zero { .. } => (self.clone(), Equal),
Finite { .. } => sin_prec_round_normal_ref(self, prec, rm),
}
}
#[inline]
pub fn sin_prec(self, prec: u64) -> (Self, Ordering) {
self.sin_prec_round(prec, Nearest)
}
#[inline]
pub fn sin_prec_ref(&self, prec: u64) -> (Self, Ordering) {
self.sin_prec_round_ref(prec, Nearest)
}
#[inline]
pub fn sin_round(self, rm: RoundingMode) -> (Self, Ordering) {
let prec = self.significant_bits();
self.sin_prec_round(prec, rm)
}
#[inline]
pub fn sin_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
self.sin_prec_round_ref(self.significant_bits(), rm)
}
#[inline]
pub fn sin_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
let o;
(*self, o) = self.sin_prec_round_ref(prec, rm);
o
}
#[inline]
pub fn sin_prec_assign(&mut self, prec: u64) -> Ordering {
self.sin_prec_round_assign(prec, Nearest)
}
#[inline]
pub fn sin_round_assign(&mut self, rm: RoundingMode) -> Ordering {
let prec = self.significant_bits();
self.sin_prec_round_assign(prec, rm)
}
}
impl Float {
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn sin_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
Self::sin_rational_prec_round_ref(&x, prec, rm)
}
pub fn sin_rational_prec_round_ref(
x: &Rational,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
assert_ne!(prec, 0);
if *x == 0u32 {
return (Self::ZERO, Equal);
}
sin_rational_helper(x, prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn sin_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
Self::sin_rational_prec_round_ref(&x, prec, Nearest)
}
#[inline]
pub fn sin_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
Self::sin_rational_prec_round_ref(x, prec, Nearest)
}
}
impl Float {
#[inline]
pub fn sin_with_period_prec_round(
self,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
self.sin_with_period_prec_round_ref(u, prec, rm)
}
pub fn sin_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 { .. } => (self.clone(), Equal),
Finite { .. } => sin_with_period_prec_round_normal_ref(self, u, prec, rm),
}
}
#[inline]
pub fn sin_with_period_prec(self, u: u64, prec: u64) -> (Self, Ordering) {
self.sin_with_period_prec_round(u, prec, Nearest)
}
#[inline]
pub fn sin_with_period_prec_ref(&self, u: u64, prec: u64) -> (Self, Ordering) {
self.sin_with_period_prec_round_ref(u, prec, Nearest)
}
#[inline]
pub fn sin_with_period_round(self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
let prec = self.significant_bits();
self.sin_with_period_prec_round(u, prec, rm)
}
#[inline]
pub fn sin_with_period_round_ref(&self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
self.sin_with_period_prec_round_ref(u, self.significant_bits(), rm)
}
#[inline]
pub fn sin_with_period(self, u: u64) -> Self {
let prec = self.significant_bits();
self.sin_with_period_prec(u, prec).0
}
#[inline]
pub fn sin_with_period_ref(&self, u: u64) -> Self {
self.sin_with_period_prec_ref(u, self.significant_bits()).0
}
#[inline]
pub fn sin_with_period_prec_round_assign(
&mut self,
u: u64,
prec: u64,
rm: RoundingMode,
) -> Ordering {
let o;
(*self, o) = self.sin_with_period_prec_round_ref(u, prec, rm);
o
}
#[inline]
pub fn sin_with_period_prec_assign(&mut self, u: u64, prec: u64) -> Ordering {
self.sin_with_period_prec_round_assign(u, prec, Nearest)
}
#[inline]
pub fn sin_with_period_round_assign(&mut self, u: u64, rm: RoundingMode) -> Ordering {
let prec = self.significant_bits();
self.sin_with_period_prec_round_assign(u, prec, rm)
}
#[inline]
pub fn sin_with_period_assign(&mut self, u: u64) {
let prec = self.significant_bits();
self.sin_with_period_prec_assign(u, prec);
}
}
impl Float {
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn sin_with_period_rational_prec_round(
x: Rational,
u: u64,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_round_ref(&x, u, prec, rm)
}
pub fn sin_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::ZERO, Equal);
}
let q = x / Rational::from(u) % Rational::ONE;
if q == 0u32 {
return (
if *x < 0u32 {
Self::NEGATIVE_ZERO
} else {
Self::ZERO
},
Equal,
);
}
sin_turns_helper(&q, prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn sin_with_period_rational_prec(x: Rational, u: u64, prec: u64) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_round_ref(&x, u, prec, Nearest)
}
#[inline]
pub fn sin_with_period_rational_prec_ref(x: &Rational, u: u64, prec: u64) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_round_ref(x, u, prec, Nearest)
}
}
impl Float {
#[inline]
pub fn sin_pi_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
self.sin_with_period_prec_round(2, prec, rm)
}
#[inline]
pub fn sin_pi_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
self.sin_with_period_prec_round_ref(2, prec, rm)
}
#[inline]
pub fn sin_pi_prec(self, prec: u64) -> (Self, Ordering) {
self.sin_with_period_prec(2, prec)
}
#[inline]
pub fn sin_pi_prec_ref(&self, prec: u64) -> (Self, Ordering) {
self.sin_with_period_prec_ref(2, prec)
}
#[inline]
pub fn sin_pi_round(self, rm: RoundingMode) -> (Self, Ordering) {
self.sin_with_period_round(2, rm)
}
#[inline]
pub fn sin_pi_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
self.sin_with_period_round_ref(2, rm)
}
#[inline]
pub fn sin_pi(self) -> Self {
let prec = self.significant_bits();
self.sin_pi_prec(prec).0
}
#[inline]
pub fn sin_pi_ref(&self) -> Self {
self.sin_pi_prec_ref(self.significant_bits()).0
}
#[inline]
pub fn sin_pi_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
self.sin_with_period_prec_round_assign(2, prec, rm)
}
#[inline]
pub fn sin_pi_prec_assign(&mut self, prec: u64) -> Ordering {
self.sin_with_period_prec_assign(2, prec)
}
#[inline]
pub fn sin_pi_round_assign(&mut self, rm: RoundingMode) -> Ordering {
self.sin_with_period_round_assign(2, rm)
}
#[inline]
pub fn sin_pi_assign(&mut self) {
let prec = self.significant_bits();
self.sin_pi_prec_assign(prec);
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn sin_pi_rational_prec_round(
x: Rational,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_round_ref(&x, 2, prec, rm)
}
#[inline]
pub fn sin_pi_rational_prec_round_ref(
x: &Rational,
prec: u64,
rm: RoundingMode,
) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_round_ref(x, 2, prec, rm)
}
#[inline]
#[allow(clippy::needless_pass_by_value)]
pub fn sin_pi_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_ref(&x, 2, prec)
}
#[inline]
pub fn sin_pi_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
Self::sin_with_period_rational_prec_ref(x, 2, prec)
}
}
impl Sin for Float {
type Output = Self;
#[inline]
fn sin(self) -> Self {
let prec = self.significant_bits();
self.sin_prec_round(prec, Nearest).0
}
}
impl Sin for &Float {
type Output = Float;
#[inline]
fn sin(self) -> Float {
self.sin_prec_round_ref(self.significant_bits(), Nearest).0
}
}
impl SinAssign for Float {
#[inline]
fn sin_assign(&mut self) {
let prec = self.significant_bits();
self.sin_prec_round_assign(prec, Nearest);
}
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_sin<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::sin_prec, x)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_sin_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::sin_rational_prec_ref, x)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_sin_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::sin_with_period_prec(x, u, prec), x)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_sin_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::sin_with_period_rational_prec_ref(x, u, prec),
x,
)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_sin_pi<T: PrimitiveFloat>(x: T) -> T
where
Float: From<T> + PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_sin_with_period(x, 2)
}
#[inline]
#[allow(clippy::type_repetition_in_bounds)]
pub fn primitive_float_sin_pi_rational<T: PrimitiveFloat>(x: &Rational) -> T
where
Float: PartialOrd<T>,
for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
{
primitive_float_sin_with_period_rational(x, 2)
}