Skip to main content

malachite_float/float/arithmetic/
sin_cos.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5//      Copyright © 2002-2025 Free Software Foundation, Inc.
6//
7//      Contributed by the Pascaline and Caramba projects, INRIA.
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
14
15// Port of MPFR's simultaneous sine and cosine. `mpfr_sin_cos` (`sin_cos.c`) reduces an argument
16// with |x| >= 2 modulo 2 pi, takes the cosine of the reduced argument, and derives the sine as
17// ±sqrt(1 - cos^2), all inside one Ziv loop that must certify both results. For precisions at or
18// above `SINCOS_THRESHOLD`, `sin`, `cos`, and `sin_cos` all use the asymptotically fast tier
19// `sin_cos_fast` (`mpfr_sincos_fast`, in the same file): the argument is reduced modulo pi/2 and
20// split into chunks of doubling bit length, each chunk's sine and cosine are summed by binary
21// splitting of the Taylor series in integer arithmetic, and the chunks are combined by the
22// angle-addition formulas.
23
24use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
25use crate::float::arithmetic::cos::{
26    NEAR_ZERO_MIN_CANCEL, cos_rational_helper, cos_rational_tiny, cos_turns_helper,
27    cos_turns_special_case, cos_with_period_prec_round_normal_ref, reduce_huge, round_bracket,
28    trig_near_zero, trig_rational_near_zero, trig_turns_near_zero,
29};
30use crate::float::arithmetic::exp::get_z_2exp;
31use crate::float::arithmetic::round_near_x::float_round_near_x;
32use crate::float::arithmetic::sin::{
33    SCALED_INPUT_EXPONENT, sin_rational_helper, sin_turns_helper, sin_turns_special_case,
34    sin_with_period_prec_round_normal_ref,
35};
36use crate::{Float, emulate_float_to_float_pair_fn, emulate_rational_to_float_pair_fn};
37use alloc::vec;
38use core::cmp::Ordering::{self, Equal};
39use core::cmp::{max, min};
40use core::mem::swap;
41use malachite_base::num::arithmetic::traits::{
42    Abs, CeilingLogBase2, FloorSqrt, IsPowerOf2, NegAssign, Parity, PowerOf2, SinCos, SinCosAssign,
43    Square, UnsignedAbs,
44};
45use malachite_base::num::basic::floats::PrimitiveFloat;
46use malachite_base::num::basic::integers::PrimitiveInt;
47use malachite_base::num::basic::traits::{
48    NaN as NaNTrait, NegativeZero as NegativeZeroTrait, One, Zero as ZeroTrait,
49};
50use malachite_base::num::comparison::traits::{EqAbs, PartialOrdAbs};
51use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
52use malachite_base::num::logic::traits::SignificantBits;
53use malachite_base::rounding_modes::RoundingMode::{self, Ceiling, Down, Exact, Nearest, Up};
54use malachite_base::{fail_on_untested_path, split_into_chunks_mut};
55use malachite_nz::integer::Integer;
56use malachite_nz::natural::arithmetic::float::round::float_can_round;
57use malachite_nz::platform::Limb;
58use malachite_q::Rational;
59
60// The outcome of one iteration of the Ziv loop in `sin_cos_prec_round_normal_ref`.
61enum SinCosStep {
62    // The working precision could not decide both results; retry at a higher one.
63    Retry,
64    // The sine and cosine at the working precision, ready for the final rounding.
65    Done(Float, Float),
66    // The input is within about 2^-cancel of an odd multiple of pi/2, so the cosine is tiny and the
67    // sine is within 2^-2cancel of ±1, with the given sign.
68    NearZeroCos { cancel: u64, sin_negative: bool },
69    // The input is within about 2^-cancel of a nonzero multiple of pi, so the sine is tiny and the
70    // cosine is within 2^-2cancel of ±1, with the given sign.
71    NearZeroSin { cancel: u64, cos_negative: bool },
72}
73
74// One iteration of the Ziv loop at working precision `m`, which the cancellation checks may raise
75// for the next iteration (the caller applies the generic increase on `Retry`).
76fn sin_cos_ziv_step(
77    x: &Float,
78    exp_x: i64,
79    prec: u64,
80    rm: RoundingMode,
81    reduce: bool,
82    m: &mut u64,
83) -> SinCosStep {
84    // A cancellation of this many bits sends a result to the near-zero path, and leaves the other
85    // one within 2^-(prec + 2) of ±1, so that it rounds from ±1 alone.
86    let near_zero_threshold = max(NEAR_ZERO_MIN_CANCEL, (prec >> 1) + 1);
87    let m_i = i64::exact_from(*m);
88    let xr;
89    let xx = if reduce {
90        // As in `mpfr_sin`: reduce x modulo 2 pi to xr, and check that xr is at least 2^(2-m) away
91        // from 0 and from ±pi, which settles the sign of the sine.
92        let c_prec = u64::exact_from(exp_x) + *m - 1;
93        let pi = Float::pi_prec(c_prec).0;
94        xr = x.ieee_remainder_prec_ref_val(&pi << 1u32, *m).0;
95        let c = pi.sub_prec_round((&xr).abs(), c_prec, Down).0;
96        let threshold = 3 - m_i;
97        let xr_small = xr == 0u32 || i64::from(xr.get_exponent().unwrap()) < threshold;
98        let c_small = c == 0u32 || i64::from(c.get_exponent().unwrap()) < threshold;
99        if xr_small || c_small {
100            // x is within 2^(4-m) of a multiple of pi (an even one if xr is small, an odd one if c
101            // is small), so |sin(x)| < 2^(5-m); the near-zero path resolves the sine directly, and
102            // the cosine is then ±1 to within 2^-2cancel.
103            let cancel = *m - 4;
104            return if cancel >= near_zero_threshold {
105                SinCosStep::NearZeroSin {
106                    cancel,
107                    cos_negative: c_small,
108                }
109            } else {
110                SinCosStep::Retry
111            };
112        }
113        &xr
114    } else {
115        x
116    };
117    // the sign of the sine
118    let sign = *xx < 0u32;
119    // c = cos(xx) rounded toward zero
120    let c = xx.cos_prec_round_ref(*m, Down).0;
121    // If no argument reduction was performed, the error is at most ulp(c), otherwise it is at most
122    // ulp(c) + 2^(2-m). Since |c| < 1, we have ulp(c) <= 2^(-m), thus the error is bounded by
123    // 2^(3-m) in that later case.
124    let exp_c = c.get_exponent().map_or(Float::MIN_EXPONENT_I64, i64::from);
125    // |cos(x)| < 2^bound_exp
126    let bound_exp = if reduce { max(exp_c, 2 - m_i) } else { exp_c } + 1;
127    if bound_exp < 0 && exp_x >= 1 {
128        let cancel = u64::exact_from(-bound_exp);
129        if cancel >= near_zero_threshold {
130            return SinCosStep::NearZeroCos {
131                cancel,
132                sin_negative: sign,
133            };
134        }
135    }
136    let err = if reduce { exp_c + m_i - 3 } else { m_i };
137    if c == 0u32
138        || err <= 0
139        || !float_can_round(c.significand_ref().unwrap(), u64::exact_from(err), prec, rm)
140    {
141        return SinCosStep::Retry;
142    }
143    // s = sqrt(1 - c^2): the square rounds up, so its absolute error is bounded by 2^(5-m) if
144    // reduce, and by 2^(2-m) otherwise; 1 - c^2 rounds to nearest, for 2^(6-m) or 2^(3-m); the
145    // square root, also to nearest, has absolute error 2^(6-m-EXP(s)) or 2^(3-m-EXP(s)).
146    let mut s = Float::ONE.sub_prec(c.square_round_ref(Ceiling).0, *m).0;
147    if s == 0u32 {
148        // 1 - c^2 rounded to zero, so sin(xx)^2 is below 2^-(m + 1): x is near a multiple of pi
149        let cancel = (*m >> 1).saturating_sub(1);
150        if reduce && cancel >= near_zero_threshold {
151            return SinCosStep::NearZeroSin {
152                cancel,
153                cos_negative: c < 0u32,
154            };
155        }
156        fail_on_untested_path("sin_cos_ziv_step, 1 - c^2 rounded to zero");
157        *m = max(*m, x.significant_bits()) << 1;
158        return SinCosStep::Retry;
159    }
160    s.sqrt_prec_assign(*m);
161    let exp_s = i64::from(s.get_exponent().unwrap());
162    // the absolute error on s is at most 2^(err - m)
163    let err = 3 + if reduce { 3 } else { 0 } - exp_s;
164    if sign {
165        s.neg_assign();
166    }
167    // |sin(x)| < 2^bound_exp
168    let bound_exp = max(exp_s, err - m_i) + 1;
169    if reduce && bound_exp < 0 {
170        let cancel = u64::exact_from(-bound_exp);
171        if cancel >= near_zero_threshold {
172            return SinCosStep::NearZeroSin {
173                cancel,
174                cos_negative: c < 0u32,
175            };
176        }
177    }
178    // put the error in the form 2^(EXP(s) - err)
179    let err = exp_s + m_i - err;
180    if err > 0 && float_can_round(s.significand_ref().unwrap(), u64::exact_from(err), prec, rm) {
181        return SinCosStep::Done(s, c);
182    }
183    if err < i64::exact_from(prec) {
184        *m += u64::exact_from(i64::exact_from(prec) - err);
185    }
186    // s is exactly ±1 (its square root rounded to nearest), so the sine is within an ulp of ±1
187    // and the working precision is doubled
188    if exp_s == 1 && s.eq_abs(&1u32) {
189        *m <<= 1;
190    }
191    SinCosStep::Retry
192}
193
194// ±1 rounded to `prec` bits under `rm`, as the value of a function known to lie within 2^(1 - err)
195// of ±1 on the side toward zero, with the ternary value; the negative case reuses the positive one
196// with the rounding mode mirrored.
197fn near_one(err: u64, negative: bool, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
198    let err = min(err, prec + 2);
199    if negative {
200        let (r, o) = float_round_near_x(&Float::ONE, err, false, prec, -rm).unwrap();
201        (-r, o.reverse())
202    } else {
203        float_round_near_x(&Float::ONE, err, false, prec, rm).unwrap()
204    }
205}
206
207// Computes sin(x) and cos(x) for a nonzero `Rational` x, rounded to precision `prec` with rounding
208// mode `rm`. (x = 0 is handled by the caller.) Neither result is ever exactly representable, so
209// `rm` must not be `Exact`.
210//
211// This shares the work of `sin_rational_helper` and `cos_rational_helper`: x is rounded once to a
212// `Float` y_f at a working precision w, both functions of y_f are taken together, and both are
213// bracketed using the Lipschitz bound |f(x) - f(y_f)| <= |x - y_f|, the rounding errors, and, for
214// an x too large to be a `Float`, the error of a single `Rational` reduction modulo 2 pi, which for
215// such an x is the dominant cost. The brackets are rounded in `Rational` arithmetic, and w is
216// raised until both resolve.
217pub(crate) fn sin_cos_rational_helper(
218    x: &Rational,
219    prec: u64,
220    rm: RoundingMode,
221) -> (Float, Float, Ordering, Ordering) {
222    assert_ne!(rm, Exact, "Inexact sin_cos");
223    let exp_x = x.floor_log_base_2_abs() + 1; // the MPFR-style exponent of x
224    // For an x so small that the cosine rounds to 1, both results come cheaply from the separate
225    // paths: the sine from its series (or the underflow rule, or, for a precision beyond 2^31 bits,
226    // the general path), and the cosine from 1.
227    if 1 - (exp_x << 1) > i64::exact_from(prec) {
228        let (s, o_s) = sin_rational_helper(x, prec, rm);
229        let (c, o_c) = cos_rational_tiny(prec, rm);
230        return (s, c, o_s, o_c);
231    }
232    // an x too small to be a `Float` at a precision that does not round its cosine to 1 needs the
233    // series paths of both functions, which is only reachable beyond 2^31 bits of precision
234    if exp_x <= Float::MIN_EXPONENT_I64 {
235        fail_on_untested_path("sin_cos_rational_helper, series paths");
236        let (s, o_s) = sin_rational_helper(x, prec, rm);
237        let (c, o_c) = cos_rational_helper(x, prec, rm);
238        return (s, c, o_s, o_c);
239    }
240    let near_zero_threshold = max(NEAR_ZERO_MIN_CANCEL, (prec >> 1) + 1);
241    let huge = exp_x >= Float::MAX_EXPONENT_I64;
242    let mut w = prec + 10;
243    let mut increment = Limb::WIDTH;
244    loop {
245        let reduced;
246        let (y, extra) = if huge {
247            reduced = reduce_huge(x, exp_x, w);
248            (&reduced, Some(2 - i64::exact_from(w)))
249        } else {
250            (x, None)
251        };
252        if *y == 0u32 {
253            // x is an exact multiple of 2 pi at the working precision; a higher precision breaks
254            // the coincidence
255            fail_on_untested_path("sin_cos_rational_helper, reduced argument is zero");
256        } else {
257            let (y_f, y_o) = Float::from_rational_prec_ref(y, w);
258            if !huge && y_o == Equal {
259                // x is exactly representable at w bits, so its sine and cosine are simply those
260                return sin_cos_prec_round_normal_ref(&y_f, prec, rm);
261            }
262            let (s_f, c_f, _, _) = y_f.sin_cos_round_ref(Nearest);
263            // The exponents of y, s_f, and c_f as `Float`s would have them (a zero result means
264            // complete cancellation).
265            let exp_y = y.floor_log_base_2_abs() + 1;
266            let exp_s = s_f
267                .get_exponent()
268                .map_or(Float::MIN_EXPONENT_I64, i64::from);
269            let exp_c = c_f
270                .get_exponent()
271                .map_or(Float::MIN_EXPONENT_I64, i64::from);
272            let w_i = i64::exact_from(w);
273            // |f(y) - f_f| <= 2^(exp_f - w) (half an ulp, doubled for safety) + |y - y_f| <=
274            // 2^(exp_y - w), plus the reduction error; so |f(y)| < 2^(bound + 2) with bound the
275            // largest of those exponents. Heavy cancellation in either function means y is close to
276            // one of its zeros, which its near-zero path resolves exactly, while the other function
277            // is then within 2^-2cancel of ±1 and rounds from ±1 alone.
278            let error_exp = max(exp_y - w_i, extra.unwrap_or(i64::MIN));
279            let bound_s = max(exp_s, error_exp) + 2;
280            let bound_c = max(exp_c, error_exp) + 2;
281            if bound_s < 0 {
282                let cancel = u64::exact_from(-bound_s);
283                if cancel >= near_zero_threshold {
284                    let (s, o_s) = trig_rational_near_zero(y, exp_y, prec, rm, extra, w, false);
285                    // 1 - |cos(x)| <= sin(x)^2 / 2 < 2^(2 bound_s - 1)
286                    let (c, o_c) = near_one((cancel << 1) + 2, c_f < 0u32, prec, rm);
287                    return (s, c, o_s, o_c);
288                }
289            }
290            if bound_c < 0 {
291                let cancel = u64::exact_from(-bound_c);
292                if cancel >= near_zero_threshold {
293                    let (c, o_c) = trig_rational_near_zero(y, exp_y, prec, rm, extra, w, true);
294                    // 1 - |sin(x)| <= cos(x)^2 < 2^(2 bound_c)
295                    let (s, o_s) = near_one((cancel << 1) + 1, s_f < 0u32, prec, rm);
296                    return (s, c, o_s, o_c);
297                }
298            }
299            let mut delta_s = Rational::power_of_2(exp_s - w_i) + Rational::power_of_2(exp_y - w_i);
300            let mut delta_c = Rational::power_of_2(exp_c - w_i) + Rational::power_of_2(exp_y - w_i);
301            if let Some(extra) = extra {
302                let e = Rational::power_of_2(extra);
303                delta_s += &e;
304                delta_c += e;
305            }
306            let s = Rational::exact_from(&s_f);
307            let c = Rational::exact_from(&c_f);
308            if let Some((s, o_s)) = round_bracket(&(&s - &delta_s), &(s + delta_s), prec, rm)
309                && let Some((c, o_c)) = round_bracket(&(&c - &delta_c), &(c + delta_c), prec, rm)
310            {
311                return (s, c, o_s, o_c);
312            }
313        }
314        w += increment;
315        increment = w >> 1;
316    }
317}
318
319// ---------- asymptotically fast implementation below (mpfr_sincos_fast) ----------
320
321// At or above this precision, `sin`, `cos`, and `sin_cos` use the binary-splitting tier
322// (`sin_cos_fast`) rather than their basic Ziv loops. Tuned on Apple Silicon with `-g tune_sincos`
323// (see `bin_util/tune.rs`), 2026-09-07: the crossover of the two `sin_cos` tiers on inputs in [1/2,
324// 1), with `sin` alone crossing at about 21800 bits and `cos` alone at about 27900. MPFR tunes the
325// same single threshold on `mpfr_sin_cos` (28990 bits on its arm build, 23323 on x86_64 core2).
326// Beyond the crossover the fast tier leads by only a few percent up to about 300000 bits.
327pub(crate) const SINCOS_THRESHOLD: u64 = 25285;
328
329// Truncates `r` to at most `prec` bits, returning the truncated integer and the number of bits
330// dropped.
331//
332// This is `reduce` from `sin_cos.c`, MPFR 4.2.2.
333fn reduce(r: &Integer, prec: u64) -> (Integer, u64) {
334    let l = r.significant_bits().saturating_sub(prec);
335    (r >> l, l)
336}
337
338// Truncates `s` and `c` by the same number of bits, so that the smaller has at most `prec` bits,
339// returning the number of bits dropped.
340//
341// This is `reduce2` from `sin_cos.c`, MPFR 4.2.2.
342fn reduce2(s: &mut Integer, c: &mut Integer, prec: u64) -> u64 {
343    let l = min(s.significant_bits(), c.significant_bits()).saturating_sub(prec);
344    *s >>= l;
345    *c >>= l;
346    l
347}
348
349const KMAX: usize = 64;
350// three arrays of KMAX entries each
351const SCRATCH_LEN: usize = 3 * KMAX;
352
353// Returns (Q0, S0, C0, m) such that S0/(Q0 2^m) approximates sin(X) with absolute error at most 9
354// 2^-prec, and C0/(Q0 2^m) approximates cos(X) with relative (and so absolute) error at most 9
355// 2^-prec, where 0 <= X = p/2^r <= 1/2.
356//
357// sin(X)/X = sum((-1)^i (p/2^r)^i/(2i+1)!, i = 0..infinity), summed by binary splitting with P(a,b)
358// = (-p)^(b-a), Q(a,b) = (2a)(2a+1) 2^r if a+1 = b (except Q(0,1) = 1) and Q(a,c) Q(c,b) otherwise,
359// and T(a,b) = 1 if a+1 = b and Q(c,b) T(a,c) + P(a,c) T(c,b) otherwise. Since P(a,b) is only
360// needed for b-a = 2^k, only the powers p^(2^k) are computed, and the factor 2^r is not stored in Q
361// but tracked as the returned power of two.
362//
363// This is `sin_bs_aux` from `sin_cos.c`, MPFR 4.2.2. Assumes prec >= 10.
364fn sin_bs_aux(p: &Integer, r: u64, prec: u64) -> (Integer, Integer, Integer, u64) {
365    if *p == 0u32 {
366        // sin(x)/x -> 1
367        fail_on_untested_path("sin_bs_aux, p == 0");
368        return (Integer::ONE, Integer::ONE, Integer::ONE, 0);
369    }
370    // check that X = p/2^r <= 1/2 (MPFR's `mpz_sizeinbase (p, 2) - r <= -1` compares in unsigned
371    // arithmetic, so it never fails; the first chunk can be exactly 1/2)
372    let p_bits = p.significant_bits();
373    assert!(p_bits < r || (p_bits == r && p.unsigned_abs_ref().is_power_of_2()));
374    let r0 = r;
375    // normalize p (non-zero here): p = pp * 2^h, then square
376    let h = p.trailing_zeros().unwrap();
377    let pp = (p >> h).square();
378    // x^2 = (p/2^r0)^2 = pp / 2^r
379    let r = (r - h) << 1;
380    // now p is odd
381    let mut scratch = vec![Integer::ZERO; SCRATCH_LEN];
382    split_into_chunks_mut!(scratch, KMAX, [t, q], ptoj); // ptoj[i] = pp^(2^i)
383    let mut log2_nb_terms = [0u64; KMAX];
384    let mut scratch_i = vec![0i64; SCRATCH_LEN];
385    split_into_chunks_mut!(scratch_i, KMAX, [mult, accu], size_ptoj);
386    let mut alloc = 2usize;
387    // 6*2^r - pp = 6*2^r*(1 - x^2/6)
388    t[0] = (const { Integer::const_from_unsigned(6) } << r) - &pp;
389    q[0] = const { Integer::const_from_unsigned(6) };
390    ptoj[0] = pp.clone();
391    ptoj[1] = (&pp).square();
392    size_ptoj[1] = i64::exact_from(ptoj[1].significant_bits());
393    log2_nb_terms[0] = 1;
394    // already take into account the factor x = p/2^r in sin(x) = x * (...): we have x^3 <
395    // 1/2^mult[0]
396    let pp_s = i64::exact_from(pp.significant_bits());
397    let p_s = i64::exact_from(p.significant_bits());
398    let r_i = i64::exact_from(r);
399    mult[0] = r_i - pp_s + i64::exact_from(r0) - p_s;
400    let prec_i = i64::exact_from(prec);
401    let mut k = 0usize;
402    let mut prec_i_have = mult[0];
403    let mut i = 2u64;
404    while prec_i_have < prec_i {
405        // i is even here. Invariant: Q[0]*Q[1]*...*Q[k] equals (2i-1)!, and we have already summed
406        // the terms of index < i in S[0]/Q[0], ..., S[k]/Q[k].
407        k += 1;
408        if k + 1 >= alloc {
409            // necessarily k + 1 == alloc
410            assert_eq!(k + 1, alloc);
411            alloc += 1;
412            assert!(k + 1 < KMAX);
413            ptoj[k + 1] = (&ptoj[k]).square(); // pp^(2^(k+1))
414            size_ptoj[k + 1] = i64::exact_from(ptoj[k + 1].significant_bits());
415        }
416        // For i even, we have Q[k] = (2i)(2i+1), T[k] = 1, then Q[k+1] = (2i+2)(2i+3), T[k+1] = 1,
417        // which reduces to T[k] = (2i+2)(2i+3) 2^r - pp, Q[k] = (2i)(2i+1)(2i+2)(2i+3).
418        assert!(k < KMAX);
419        log2_nb_terms[k] = 1;
420        let two_i = i << 1;
421        q[k] = Integer::from((two_i + 2) * (two_i + 3));
422        t[k] = (&q[k] << r) - &pp;
423        q[k] *= Integer::from(two_i * (two_i + 1));
424        // the next term of the series is divided by Q[k] and multiplied by pp^2/2^(2r), thus the
425        // multiplicative factor is < 1/2^mult[k]
426        mult[k] = i64::exact_from(q[k].significant_bits()) + (r_i << 1) - size_ptoj[1] - 1;
427        // the absolute contribution of the next term is 1/2^accu[k]
428        accu[k] = if k == 0 {
429            mult[k]
430        } else {
431            mult[k] + accu[k - 1]
432        };
433        prec_i_have = accu[k]; // the current term is < 1/2^accu[k]
434        let mut j = (i + 2) >> 1;
435        let mut l = 1usize;
436        while j.even() {
437            // combine and reduce
438            assert!(k >= 1);
439            t[k] *= &ptoj[l];
440            let mut tk1 = &t[k - 1] * &q[k];
441            tk1 <<= r << l;
442            tk1 += &t[k];
443            t[k - 1] = tk1;
444            let qk = q[k].clone();
445            q[k - 1] *= &qk;
446            // the number of terms in S[k-1] is a power of 2 by construction
447            log2_nb_terms[k - 1] += 1;
448            prec_i_have = i64::exact_from(qk.significant_bits());
449            mult[k - 1] += prec_i_have + i64::exact_from(r << l) - size_ptoj[l] - 1;
450            accu[k - 1] = if k == 1 {
451                mult[k - 1]
452            } else {
453                mult[k - 1] + accu[k - 2]
454            };
455            prec_i_have = accu[k - 1];
456            l += 1;
457            j >>= 1;
458            k -= 1;
459        }
460        i += 2;
461    }
462    // Accumulate all products in T[0] and Q[0]. Warning: contrary to above, here we do not have
463    // log2_nb_terms[k-1] = log2_nb_terms[k]+1.
464    let mut h = 0u64; // number of accumulated terms in the right part T[k]/Q[k]
465    while k > 0 {
466        t[k] *= &ptoj[usize::exact_from(log2_nb_terms[k - 1])];
467        let mut tk1 = &t[k - 1] * &q[k];
468        h += u64::power_of_2(log2_nb_terms[k]);
469        tk1 <<= r * h;
470        tk1 += &t[k];
471        t[k - 1] = tk1;
472        let qk = q[k].clone();
473        q[k - 1] *= qk;
474        k -= 1;
475    }
476    // implicit multiplier 2^r for Q0
477    let mut m = i64::exact_from(r0) + r_i * (i64::exact_from(i) - 1);
478    // At this point T[0]/(2^m Q[0]) is an approximation of sin(x) where the first neglected term
479    // has contribution < 1/2^prec; since the series has alternating signs, the error is < 1/2^prec.
480    //
481    // We truncate Q0 to prec bits: the relative error is at most 2^(1-prec), which means that Q0 =
482    // Q[0] (1 + theta) with |theta| <= 2^(1-prec), up to a power of two.
483    let (q0, l) = reduce(&q[0], prec);
484    m += i64::exact_from(l);
485    let (t0, l) = reduce(&t[0], prec);
486    m -= i64::exact_from(l);
487    // multiply by x = p/2^m
488    let (s0, l) = reduce(&(t0 * p), prec); // S0 = T[0] (1 + theta)^2 up to a power of two
489    m -= i64::exact_from(l);
490    // sin(X) ~ S0/Q0 (1 + theta)^3 + err with |theta| <= 2^(1-prec) and |err| <= 2^(-prec), thus
491    // since |S0/Q0| <= 1: |sin(X) - S0/Q0| <= 4 |theta S0/Q0| + |err| <= 9 2^(-prec)
492    //
493    // Compute cos(X) from sin(X): sqrt(1 - (S/Q)^2) = sqrt(Q^2 - S^2)/Q = sqrt(Q0^2 2^(2m) -
494    // S0^2)/Q0. Write S/Q = sin(X) + eps with |eps| <= 9 2^(-prec); then sqrt(Q^2 - S^2) = Q cos(X)
495    // (1 + eps4) with |eps4| <= 9 2^(-prec), since |Q| >= 2^(prec-1) (see sin_cos.c for the steps).
496    // We assume that Q0 2^m >= 2^(prec-1).
497    let m = u64::exact_from(m);
498    assert!(m + q0.significant_bits() >= prec);
499    let c0 = Integer::from(
500        (((&q0).square() << (m << 1)) - (&s0).square())
501            .unsigned_abs()
502            .floor_sqrt(),
503    );
504    (q0, s0, c0, m)
505}
506
507// Returns approximations s and c of sin(x) and cos(x) at precision `prec_s`, and err such that the
508// relative error of each is bounded by 2^err ulps. Assumes 0 < x < pi/4 and prec_s >= 10.
509//
510// This is `sincos_aux` from `sin_cos.c`, MPFR 4.2.2.
511fn sincos_aux(x: &Float, prec_s: u64) -> (Float, Float, u64) {
512    let mut x2 = x.clone(); // exact
513    let mut q_acc = Integer::ONE;
514    let mut l = 0i64;
515    let mut s_acc = Integer::ZERO; // sin(0) = S/(2^l Q), exact
516    let mut c_acc = Integer::ONE; // cos(0) = C/(2^l Q), exact
517    // Invariant: x = X + x2/2^(sh-1), where the part X was already treated, S/(2^l Q) ~ sin(X),
518    // C/(2^l Q) ~ cos(X), and x2/2^(sh-1) < pi/4. sh-1 is the number of already shifted bits in x2.
519    let mut sh = 1u64;
520    let mut j = 0u64;
521    while x2 != 0u32 && sh <= prec_s {
522        let (q2, s2, c2, l2) = if sh > prec_s >> 1 {
523            // sin(x) = x + O(x^3), cos(x) = 1 + O(x^2)
524            let (s2, e) = get_z_2exp(x2.clone()); // S2/2^l2 = x2
525            let mut l2 = -e;
526            l2 += i64::exact_from(sh) - 1;
527            let q2 = Integer::ONE;
528            let c2 = Integer::power_of_2(u64::exact_from(l2));
529            x2 = Float::ZERO;
530            (q2, s2, c2, l2)
531        } else {
532            // y <- trunc(x2 * 2^sh) = trunc(x * 2^(2 sh - 1))
533            x2 <<= sh; // exact
534            // round toward zero: now 0 <= x2 < 2^sh, thus 0 <= x2/2^(sh-1) < 2^(1-sh)
535            let y = Integer::rounding_from(&x2, Down).0;
536            if y == 0u32 {
537                sh <<= 1;
538                j += 1;
539                continue;
540            }
541            let x2_prec = x2.get_prec().unwrap();
542            // should be exact
543            let (d, o) = x2.sub_prec_round(Float::exact_from(&y), x2_prec, Exact);
544            assert_eq!(o, Equal);
545            x2 = d;
546            let (q2, s2, c2, l2) = sin_bs_aux(&y, (sh << 1) - 1, prec_s);
547            // we now have |S2/Q2/2^l2 - sin(X)| <= 9 2^(-prec_s) and |C2/Q2/2^l2 - cos(X)| <= 6
548            // 2^(-prec_s), with X = y/2^(2 sh - 1)
549            (q2, s2, c2, i64::exact_from(l2))
550        };
551        if sh == 1 {
552            // S = 0, C = 1
553            l = l2;
554            q_acc = q2;
555            s_acc = s2;
556            c_acc = c2;
557        } else {
558            // s <- s c2 + c s2, c <- c c2 - s s2, using Karatsuba: a = s + c, b = s2 + c2, t = a b,
559            // d = s s2, e = c c2, s <- t - d - e, c <- e - d
560            let a = &s_acc + &c_acc;
561            let e = c_acc * &c2;
562            let b = c2 + &s2;
563            let d = s2 * &s_acc;
564            let t = a * b;
565            s_acc = t - &d - &e;
566            c_acc = e - d;
567            q_acc *= q2;
568            // after j loops, the error is <= (11j - 2) 2^(prec_s)
569            l += l2;
570            // reduce Q to prec_s bits
571            let (qr, lq) = reduce(&q_acc, prec_s);
572            q_acc = qr;
573            l += i64::exact_from(lq);
574            // reduce S, C to prec_s bits, error <= 11 j 2^(prec_s)
575            l -= i64::exact_from(reduce2(&mut s_acc, &mut c_acc, prec_s));
576        }
577        sh <<= 1;
578        j += 1;
579    }
580    let mut j = 11 * j;
581    let mut err = 0u64;
582    while j > 1 {
583        j = j.div_ceil(2);
584        err += 1;
585    }
586    let q_f = Float::exact_from(&q_acc);
587    let s = Float::from_integer_prec(s_acc, prec_s)
588        .0
589        .div_prec_val_ref(&q_f, prec_s)
590        .0
591        >> l;
592    let c = Float::from_integer_prec(c_acc, prec_s)
593        .0
594        .div_prec(q_f, prec_s)
595        .0
596        >> l;
597    (s, c, err)
598}
599
600// Computes sin(x) and/or cos(x) for a finite nonzero `Float` x, rounded to precision `prec` with
601// rounding mode `rm`, by binary splitting: the argument is reduced modulo pi/2 and split into
602// chunks of doubling bit length, each chunk's sine and cosine are summed by binary splitting of the
603// Taylor series in integer arithmetic, and the chunks are combined by the angle-addition formulas.
604// Only the selected results are rounded and returned.
605//
606// This is `mpfr_sincos_fast` from `sin_cos.c`, MPFR 4.2.2.
607pub(crate) fn sin_cos_fast(
608    x: &Float,
609    prec: u64,
610    rm: RoundingMode,
611    want_sin: bool,
612    want_cos: bool,
613) -> (Option<(Float, Ordering)>, Option<(Float, Ordering)>) {
614    let mut w = prec;
615    w += w.ceiling_log_base_2() + 9; // ensures w >= 10 (needed by sincos_aux)
616    let mut increment = Limb::WIDTH;
617    // 1686629713 / 2^31, just below pi/4
618    let pi_over_4 = const { Float::const_from_unsigned(1686629713) } >> 31u32;
619    let exp_x = i64::from(x.get_exponent().unwrap());
620    loop {
621        let (ts, tc, err) = if *x > 0u32 && *x <= pi_over_4 {
622            // if 0 < x <= pi/4, we can call sincos_aux directly
623            sincos_aux(x, w)
624        } else if *x < 0u32 && *x >= -&pi_over_4 {
625            // if -pi/4 <= x < 0, use sin(-x) = -sin(x)
626            let (ts, tc, err) = sincos_aux(&-x, w);
627            (-ts, tc, err)
628        } else {
629            // argument reduction is needed
630            let pi = Float::pi_prec(if exp_x > 0 {
631                w + u64::exact_from(exp_x)
632            } else {
633                w
634            })
635            .0 >> 1u32; // pi/2
636            // x = q (pi/2 + eps1) + x_red + eps2, where |eps1| <= 1/2 ulp(pi/2) =
637            // 2^(-w-max(0,EXP(x))) and eps2 <= 1/2 ulp(x_red) <= 1/2 ulp(pi/2) = 2^(-w). Since |q|
638            // <= x/(pi/2) <= |x|, we have q |eps1| <= 2^(-w), thus |x - q pi/2 - x_red| <= 2^(1-w).
639            let (mut x_red, _, q) = x.ieee_remainder_and_quotient_bits_prec_ref_ref(&pi, w);
640            // now -pi/4 <= x_red <= pi/4: if x_red < 0, consider -x_red
641            let neg = x_red < 0u32;
642            if neg {
643                x_red.neg_assign();
644            }
645            let (mut ts, mut tc, mut err) = sincos_aux(&x_red, w);
646            err += 1; // to take into account the argument reduction
647            if neg {
648                // sin(-x) = -sin(x), cos(-x) = cos(x)
649                ts.neg_assign();
650            }
651            if q & 2 != 0 {
652                // sin(x + pi) = -sin(x), cos(x + pi) = -cos(x)
653                ts.neg_assign();
654                tc.neg_assign();
655            }
656            if q.odd() {
657                // sin(x + pi/2) = cos(x), cos(x + pi/2) = -sin(x)
658                ts.neg_assign();
659                swap(&mut ts, &mut tc);
660            }
661            (ts, tc, err)
662        };
663        // adjust errors with respect to absolute values
664        let w_i = i64::exact_from(w);
665        let err_i = i64::exact_from(err);
666        let can_round = |t: &Float| {
667            t.get_exponent().is_some_and(|e| {
668                let bits = w_i - (err_i - i64::from(e));
669                bits > 0
670                    && float_can_round(
671                        t.significand_ref().unwrap(),
672                        u64::exact_from(bits),
673                        prec,
674                        rm,
675                    )
676            })
677        };
678        if (!want_sin || can_round(&ts)) && (!want_cos || can_round(&tc)) {
679            return (
680                want_sin.then(|| Float::from_float_prec_round(ts, prec, rm)),
681                want_cos.then(|| Float::from_float_prec_round(tc, prec, rm)),
682            );
683        }
684        w += increment;
685        increment = w >> 1;
686    }
687}
688
689// This is mpfr_sin_cos from sin_cos.c, MPFR 4.2.2, including the `mpfr_sincos_fast` tier for
690// precisions at or above `SINCOS_THRESHOLD`, with the near-zero paths of `sin` and `cos` added for
691// inputs extremely close to a zero of either function. Both results have precision `prec`, where
692// MPFR allows two precisions and works at the larger.
693fn sin_cos_prec_round_normal_ref(
694    x: &Float,
695    prec: u64,
696    rm: RoundingMode,
697) -> (Float, Float, Ordering, Ordering) {
698    assert_ne!(rm, Exact, "Inexact sin_cos");
699    let exp_x = i64::from(x.get_exponent().unwrap());
700    let mut m = prec + prec.ceiling_log_base_2() + 13;
701    // When x is close to 0, say 2^(-k), then there is a cancellation of about 2k bits in
702    // 1-cos(x)^2, and both results may round from x and 1 alone: sin(x) = x - x^3/6 + ... has error
703    // below 2^(3 EXP(x) - 2), and cos(x) = 1 - x^2/2 + ... has error below 2^(2 EXP(x) - 1). MPFR
704    // tries the sine first and then the cosine; here the cosine's bound is the weaker one, and the
705    // reference value 1 always rounds, so it decides.
706    if exp_x < 0 {
707        let neg_two_exp = u64::exact_from(-(exp_x << 1));
708        let err_cos = neg_two_exp + 1;
709        if err_cos > prec + 1
710            && let Some((s, o_s)) =
711                float_round_near_x(x, min(neg_two_exp + 2, prec + 2), false, prec, rm)
712        {
713            let (c, o_c) = near_one(err_cos, false, prec, rm);
714            return (s, c, o_s, o_c);
715        }
716        m += neg_two_exp;
717    }
718    if prec >= SINCOS_THRESHOLD {
719        let (s, c) = sin_cos_fast(x, prec, rm, true, true);
720        let (s, o_s) = s.unwrap();
721        let (c, o_c) = c.unwrap();
722        return (s, c, o_s, o_c);
723    }
724    sin_cos_basic(x, exp_x, m, prec, rm)
725}
726
727// The basic tier of `sin_cos_prec_round_normal_ref`: the Ziv loop of `mpfr_sin_cos` starting at
728// working precision `m`, for a finite nonzero x of exponent `exp_x` that the small-input shortcut
729// did not settle.
730pub(crate) fn sin_cos_basic(
731    x: &Float,
732    exp_x: i64,
733    mut m: u64,
734    prec: u64,
735    rm: RoundingMode,
736) -> (Float, Float, Ordering, Ordering) {
737    let reduce = exp_x >= 2;
738    let mut increment = Limb::WIDTH;
739    loop {
740        match sin_cos_ziv_step(x, exp_x, prec, rm, reduce, &mut m) {
741            SinCosStep::Done(s, c) => {
742                let (s, o_s) = Float::from_float_prec_round(s, prec, rm);
743                let (c, o_c) = Float::from_float_prec_round(c, prec, rm);
744                return (s, c, o_s, o_c);
745            }
746            SinCosStep::NearZeroCos {
747                cancel,
748                sin_negative,
749            } => {
750                // 1 - |sin(x)| <= cos(x)^2 < 2^-2cancel
751                let (c, o_c) = trig_near_zero(x, prec, rm, cancel, true);
752                let (s, o_s) = near_one((cancel << 1) + 1, sin_negative, prec, rm);
753                return (s, c, o_s, o_c);
754            }
755            SinCosStep::NearZeroSin {
756                cancel,
757                cos_negative,
758            } => {
759                // 1 - |cos(x)| <= sin(x)^2 / 2 < 2^-(2cancel + 1)
760                let (s, o_s) = trig_near_zero(x, prec, rm, cancel, false);
761                let (c, o_c) = near_one((cancel << 1) + 2, cos_negative, prec, rm);
762                return (s, c, o_s, o_c);
763            }
764            SinCosStep::Retry => {}
765        }
766        m += increment;
767        increment = m >> 1;
768    }
769}
770
771// One Ziv iteration for the sine and cosine of a fraction of a turn q, given t = 2 pi q (1 +
772// theta)^3 with |theta| <= 2^-w, rounded to w bits. Returns both results when they are settled,
773// either from the values at the working precision or, for a result tiny enough, from the exact
774// near-zero path, with the other then rounded from ±1; returns `None` if the working precision
775// must be raised. `q` produces the exact fraction for the near-zero path, and `sin_near_zero` says
776// whether q is large enough for a tiny sine to mean cancellation rather than a tiny q.
777fn sin_cos_turns_step(
778    t: &Float,
779    w: u64,
780    prec: u64,
781    rm: RoundingMode,
782    sin_near_zero: bool,
783    q: impl Fn() -> Rational,
784) -> Option<(Float, Float, Ordering, Ordering)> {
785    // A cancellation of this many bits sends a result to the near-zero path, and leaves the other
786    // one within 2^-(prec + 2) of ±1, so that it rounds from ±1 alone.
787    let near_zero_threshold = max(NEAR_ZERO_MIN_CANCEL, (prec >> 1) + 1);
788    // since w >= 2, |(1 + theta)^3 - 1| <= 4 theta, so t = 2 pi q + e with |e| <= 2^(EXP(t) + 2 -
789    // w), and both sin and cos move by at most |e|
790    let w_i = i64::exact_from(w);
791    let err_t = i64::from(t.get_exponent().unwrap()) + 2 - w_i;
792    // Both rounded away from zero, so that neither is zero (t is not a multiple of pi/2, being a
793    // nonzero `Float`) and the computed magnitudes bound the true ones.
794    let (s, c, _, _) = t.sin_cos_prec_round_ref(w, Up);
795    let exp_s = i64::from(s.get_exponent().unwrap());
796    let exp_c = i64::from(c.get_exponent().unwrap());
797    // |sin(2 pi q)| <= |s| + |e| < 2^bound_s, and likewise for the cosine
798    let bound_s = max(exp_s, err_t) + 1;
799    let bound_c = max(exp_c, err_t) + 1;
800    // A tiny sine with q not itself tiny means q is close to a multiple of 1/2, and a tiny cosine
801    // means it is close to an odd multiple of 1/4. Either is resolved exactly by the near-zero
802    // path, where the Ziv loop would need its precision raised by the whole cancellation, and the
803    // other function is then within 2^-2cancel of ±1 and rounds from ±1 alone.
804    if bound_s < 0 && sin_near_zero {
805        let cancel = u64::exact_from(-bound_s);
806        if cancel >= near_zero_threshold
807            && let Some((s, o_s)) = trig_turns_near_zero(&q(), prec, rm, false)
808        {
809            // 1 - |cos(2 pi q)| <= sin(2 pi q)^2 / 2 < 2^(2 bound_s - 1)
810            let (c, o_c) = near_one((cancel << 1) + 2, c < 0u32, prec, rm);
811            return Some((s, c, o_s, o_c));
812        }
813    }
814    if bound_c < 0 {
815        let cancel = u64::exact_from(-bound_c);
816        if cancel >= near_zero_threshold
817            && let Some((c, o_c)) = trig_turns_near_zero(&q(), prec, rm, true)
818        {
819            // 1 - |sin(2 pi q)| <= cos(2 pi q)^2 < 2^(2 bound_c)
820            let (s, o_s) = near_one((cancel << 1) + 1, s < 0u32, prec, rm);
821            return Some((s, c, o_s, o_c));
822        }
823    }
824    // The total error on each result is at most |e| + ulp, bounded by 2^(EXP + 1 - w) if err_t <=
825    // EXP - w and by 2^(err_t + 1) otherwise; then normalized for can_round. For the sine, |sin(t)|
826    // <= |t| gives EXP(s) <= EXP(t) + 1, so its ulp is at most 2^err_t / 2 and the second bound
827    // always applies.
828    let err_s = exp_s - err_t - 1;
829    let err_c = exp_c
830        - if err_t <= exp_c - w_i {
831            exp_c - w_i + 1
832        } else {
833            err_t + 1
834        };
835    if err_s > 0
836        && err_c > 0
837        && float_can_round(
838            s.significand_ref().unwrap(),
839            u64::exact_from(err_s),
840            prec,
841            rm,
842        )
843        && float_can_round(
844            c.significand_ref().unwrap(),
845            u64::exact_from(err_c),
846            prec,
847            rm,
848        )
849    {
850        let (s, o_s) = Float::from_float_prec_round(s, prec, rm);
851        let (c, o_c) = Float::from_float_prec_round(c, prec, rm);
852        return Some((s, c, o_s, o_c));
853    }
854    None
855}
856
857// Computes sin(2 pi x/u) and cos(2 pi x/u) for a finite nonzero `Float` x and a nonzero u, rounded
858// to precision `prec` with rounding mode `rm`. `rm` may be `Exact` only when both results are
859// exact, that is, when x/u is a multiple of 1/4.
860//
861// MPFR has no combined function here. This joins the `mpfr_sinu` and `mpfr_cosu` ports (see
862// `sin_with_period_prec_round_normal_ref` and `cos_with_period_prec_round_normal_ref`) around one
863// approximation of 2 pi x/u per Ziv iteration, and one `sin_cos` of it, with the near-zero paths of
864// both.
865pub(crate) fn sin_cos_with_period_prec_round_normal_ref(
866    x: &Float,
867    u: u64,
868    prec: u64,
869    rm: RoundingMode,
870) -> (Float, Float, Ordering, Ordering) {
871    // Range reduction, as in the sine: xr = x mod u, with the sign of x, exactly.
872    let xr;
873    let xp = if x.lt_abs(&u) {
874        x
875    } else {
876        let p = i64::exact_from(x.get_prec().unwrap()) - i64::from(x.get_exponent().unwrap());
877        let (r, o) =
878            x.rem_unsigned_prec_round_ref(u, u64::WIDTH + u64::exact_from(max(p, 0)), Exact);
879        assert_eq!(o, Equal);
880        if r == 0u32 {
881            // x is a multiple of u: the sine is zero, with the sign of x, and the cosine is 1
882            return (
883                if *x < 0u32 {
884                    Float::NEGATIVE_ZERO
885                } else {
886                    Float::ZERO
887                },
888                Float::one_prec(prec),
889                Equal,
890                Equal,
891            );
892        }
893        xr = r;
894        &xr
895    };
896    // now |xp/u| < 1
897    let exp_x = i64::from(xp.get_exponent().unwrap());
898    // For x/u small, the cosine rounds from 1 alone: |cos(2 pi x/u) - 1| < 2^5 (x/u)^2 <= 2^(5 + 2
899    // EXP(x) - 2 log2u), with u >= 2^log2u, as in the cosine. The sine has no such shortcut, being
900    // close to 2 pi x/u, which must still be computed, so it takes its own path; there is nothing
901    // to share.
902    let log2u = if u == 1 {
903        0
904    } else {
905        i64::exact_from(u.ceiling_log_base_2()) - 1
906    };
907    let err = ((log2u - exp_x) << 1) - 5;
908    if err > 0 {
909        let err = u64::exact_from(err);
910        if err > prec + 1 {
911            // such a small x/u is never a special case, and its cosine is never exact
912            assert_ne!(rm, Exact, "Inexact sin_cos_with_period");
913            let (s, o_s) = sin_with_period_prec_round_normal_ref(xp, u, prec, rm);
914            let (c, o_c) = near_one(err, false, prec, rm);
915            return (s, c, o_s, o_c);
916        }
917    }
918    let u_bits = i64::exact_from(u.significant_bits());
919    // The special cases need |x/u| >= 1/20, so the exponent test skips the `Rational` construction
920    // for the small x that would make it expensive. Only a fraction of a turn with both closed
921    // forms (a multiple of 1/4, or a denominator of 3, 6, 8, or 12) is taken from them; a fifth,
922    // tenth, or twentieth of a turn has only one, and goes through the loop like any other input.
923    if exp_x >= u_bits - 5 {
924        let q = Rational::exact_from(xp) / Rational::from(u);
925        if let Some((s, o_s)) = sin_turns_special_case(&q, prec, rm)
926            && let Some((c, o_c)) = cos_turns_special_case(&q, prec, rm)
927        {
928            return (s, c, o_s, o_c);
929        }
930    }
931    // Only the exact cases can be rounded exactly
932    assert_ne!(rm, Exact, "Inexact sin_cos_with_period");
933    if exp_x <= SCALED_INPUT_EXPONENT {
934        // 2 pi x/u is within a few bits of the bottom of the exponent range, where the sine may
935        // underflow while the cosine has not rounded to 1, which needs a precision beyond 2^31
936        // bits: the separate functions handle each.
937        fail_on_untested_path("sin_cos_with_period_prec_round_normal_ref, tiny x/u");
938        let (s, o_s) = sin_with_period_prec_round_normal_ref(xp, u, prec, rm);
939        let (c, o_c) = cos_with_period_prec_round_normal_ref(xp, u, prec, rm);
940        return (s, c, o_s, o_c);
941    }
942    // For x large, since argument reduction is expensive, we want to avoid any failure in Ziv's
943    // strategy, thus we take into account expx too.
944    let mut prec_t =
945        prec + u64::exact_from(max(exp_x, i64::exact_from(prec.ceiling_log_base_2()))) + 8;
946    let mut increment = Limb::WIDTH;
947    let u_float = Float::from(u);
948    // A tiny sine with x/u not itself tiny means cancellation; for a tiny x/u the sine is simply
949    // close to 2 pi x/u, and its `Rational` form would be expensive.
950    let sin_near_zero = exp_x >= u_bits - 2;
951    loop {
952        // t = 2*pi*x/u * (1 + theta)^3 where |theta| <= 2^-prec_t, from rounding pi, the product,
953        // and the quotient
954        let mut t = Float::pi_prec(prec_t).0 << 1u32;
955        t.mul_prec_assign_ref(xp, prec_t);
956        t.div_prec_assign_ref(&u_float, prec_t);
957        if let Some(result) = sin_cos_turns_step(&t, prec_t, prec, rm, sin_near_zero, || {
958            Rational::exact_from(xp) / Rational::from(u)
959        }) {
960            return result;
961        }
962        prec_t += increment;
963        increment = prec_t >> 1;
964    }
965}
966
967impl Float {
968    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, rounding both
969    /// results to the specified precision and with the specified rounding mode. The [`Float`] is
970    /// taken by value. Two [`Ordering`]s are also returned, indicating whether the rounded sine and
971    /// cosine are less than, equal to, or greater than the exact values. Although `NaN`s are not
972    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`
973    /// for it.
974    ///
975    /// The results are the same as those of [`Float::sin_prec_round`] and
976    /// [`Float::cos_prec_round`], but the argument reduction and most of the work are shared, so
977    /// this is faster than the two calls when both values are needed.
978    ///
979    /// See [`RoundingMode`] for a description of the possible rounding modes.
980    ///
981    /// $$
982    /// f(x,p,m) = (\sin x+\varepsilon_s, \cos x+\varepsilon_c).
983    /// $$
984    /// - If $x$ is not finite, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or assumed to be
985    ///   0.
986    /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin
987    ///   x|\rfloor-p+1}$ and $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos x|\rfloor-p+1}$.
988    /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon_s| \leq 2^{\lfloor\log_2 |\sin
989    ///   x|\rfloor-p}$ and $|\varepsilon_c| \leq 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
990    ///
991    /// If the outputs have a precision, it is `prec`.
992    ///
993    /// Special cases:
994    /// - $f(\text{NaN},p,m)=(\text{NaN},\text{NaN})$
995    /// - $f(\pm\infty,p,m)=(\text{NaN},\text{NaN})$
996    /// - $f(\pm0.0,p,m)=(\pm0.0,1.0)$
997    ///
998    /// Overflow and underflow:
999    /// - Since $|\sin x|\leq 1$ and $|\cos x|\leq 1$, the results never overflow.
1000    /// - Each result underflows exactly as [`Float::sin_prec_round`] or [`Float::cos_prec_round`]
1001    ///   does: the sine for an input within $2^{-2^{30}}$ of a nonzero multiple of $\pi$ or of
1002    ///   magnitude $2^{-2^{30}}$ rounded toward zero, and the cosine for an input within
1003    ///   $2^{-2^{30}}$ of an odd multiple of $\pi/2$, either of which takes more than $2^{30}$ bits
1004    ///   of precision. See those functions for the values returned.
1005    ///
1006    /// If you know you'll be using `Nearest`, consider using [`Float::sin_cos_prec`] instead. If
1007    /// you know that your target precision is the precision of the input, consider using
1008    /// [`Float::sin_cos_round`] instead. If both of these things are true, consider using
1009    /// [`Float::sin_cos`] instead.
1010    ///
1011    /// # Worst-case complexity
1012    /// $T(n, m, e) = O(n (\log n)^3 \log\log n + (n+m+e) (\log (n+m+e))^2 \log\log (n+m+e))$
1013    ///
1014    /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1015    ///
1016    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1017    /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1018    /// a negative one): the sine and cosine at working precision $n$ (for large $n$ by binary
1019    /// splitting of the Taylor series, otherwise the cosine, from which the sine is derived) cost
1020    /// the first term, and for $|x| \geq 2$ the argument is reduced modulo $2\pi$, which requires
1021    /// $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input.
1022    ///
1023    /// # Panics
1024    /// Panics if `rm` is `Exact`, since the sine and cosine of a finite nonzero [`Float`] are never
1025    /// exactly representable, or if `prec` is zero.
1026    ///
1027    /// # Examples
1028    /// ```
1029    /// use malachite_base::rounding_modes::RoundingMode::*;
1030    /// use malachite_float::Float;
1031    /// use std::cmp::Ordering::*;
1032    ///
1033    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 100)
1034    ///     .0
1035    ///     .sin_cos_prec_round(5, Floor);
1036    /// assert_eq!(s.to_string(), "0.812");
1037    /// assert_eq!(c.to_string(), "0.531");
1038    /// assert_eq!(o_s, Less);
1039    /// assert_eq!(o_c, Less);
1040    ///
1041    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 100)
1042    ///     .0
1043    ///     .sin_cos_prec_round(5, Ceiling);
1044    /// assert_eq!(s.to_string(), "0.844");
1045    /// assert_eq!(c.to_string(), "0.562");
1046    /// assert_eq!(o_s, Greater);
1047    /// assert_eq!(o_c, Greater);
1048    ///
1049    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 100)
1050    ///     .0
1051    ///     .sin_cos_prec_round(20, Nearest);
1052    /// assert_eq!(s.to_string(), "0.84147072");
1053    /// assert_eq!(c.to_string(), "0.54030228");
1054    /// assert_eq!(o_s, Less);
1055    /// assert_eq!(o_c, Less);
1056    /// ```
1057    #[inline]
1058    pub fn sin_cos_prec_round(
1059        self,
1060        prec: u64,
1061        rm: RoundingMode,
1062    ) -> (Self, Self, Ordering, Ordering) {
1063        self.sin_cos_prec_round_ref(prec, rm)
1064    }
1065
1066    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, rounding both
1067    /// results to the specified precision and with the specified rounding mode. The [`Float`] is
1068    /// taken by reference. Two [`Ordering`]s are also returned, indicating whether the rounded sine
1069    /// and cosine are less than, equal to, or greater than the exact values.
1070    ///
1071    /// See [`Float::sin_cos_prec_round`] for the error bounds, the special cases, overflow and
1072    /// underflow, and the complexity; this function behaves the same way.
1073    ///
1074    /// # Panics
1075    /// Panics if `rm` is `Exact`, since the sine and cosine of a finite nonzero [`Float`] are never
1076    /// exactly representable, or if `prec` is zero.
1077    ///
1078    /// # Examples
1079    /// ```
1080    /// use malachite_base::rounding_modes::RoundingMode::*;
1081    /// use malachite_float::Float;
1082    /// use std::cmp::Ordering::*;
1083    ///
1084    /// let x = Float::from_unsigned_prec(1u32, 100).0;
1085    /// let (s, c, o_s, o_c) = x.sin_cos_prec_round_ref(5, Floor);
1086    /// assert_eq!(s.to_string(), "0.812");
1087    /// assert_eq!(c.to_string(), "0.531");
1088    /// assert_eq!(o_s, Less);
1089    /// assert_eq!(o_c, Less);
1090    ///
1091    /// let (s, c, o_s, o_c) = x.sin_cos_prec_round_ref(20, Nearest);
1092    /// assert_eq!(s.to_string(), "0.84147072");
1093    /// assert_eq!(c.to_string(), "0.54030228");
1094    /// assert_eq!(o_s, Less);
1095    /// assert_eq!(o_c, Less);
1096    /// ```
1097    pub fn sin_cos_prec_round_ref(
1098        &self,
1099        prec: u64,
1100        rm: RoundingMode,
1101    ) -> (Self, Self, Ordering, Ordering) {
1102        assert_ne!(prec, 0);
1103        match &self.0 {
1104            NaN | Infinity { .. } => (Self::NAN, Self::NAN, Equal, Equal),
1105            // sin(±0) = ±0 and cos(±0) = 1, exactly
1106            Zero { .. } => (self.clone(), Self::one_prec(prec), Equal, Equal),
1107            Finite { .. } => sin_cos_prec_round_normal_ref(self, prec, rm),
1108        }
1109    }
1110
1111    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, rounding both
1112    /// results to the nearest value of the specified precision. The [`Float`] is taken by value.
1113    /// Two [`Ordering`]s are also returned, indicating whether the rounded sine and cosine are less
1114    /// than, equal to, or greater than the exact values.
1115    ///
1116    /// If a result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1117    /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1118    /// the `Nearest` rounding mode.
1119    ///
1120    /// See [`Float::sin_cos_prec_round`] for the error bounds, the special cases, overflow and
1121    /// underflow, and the complexity; this function behaves the same way with `Nearest`.
1122    ///
1123    /// If you want to use a rounding mode other than `Nearest`, consider using
1124    /// [`Float::sin_cos_prec_round`] instead. If you know that your target precision is the
1125    /// precision of the input, consider using [`Float::sin_cos`] instead.
1126    ///
1127    /// # Panics
1128    /// Panics if `prec` is zero.
1129    ///
1130    /// # Examples
1131    /// ```
1132    /// use malachite_float::Float;
1133    /// use std::cmp::Ordering::*;
1134    ///
1135    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 100).0.sin_cos_prec(5);
1136    /// assert_eq!(s.to_string(), "0.844");
1137    /// assert_eq!(c.to_string(), "0.531");
1138    /// assert_eq!(o_s, Greater);
1139    /// assert_eq!(o_c, Less);
1140    ///
1141    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 100).0.sin_cos_prec(20);
1142    /// assert_eq!(s.to_string(), "0.84147072");
1143    /// assert_eq!(c.to_string(), "0.54030228");
1144    /// assert_eq!(o_s, Less);
1145    /// assert_eq!(o_c, Less);
1146    /// ```
1147    #[inline]
1148    pub fn sin_cos_prec(self, prec: u64) -> (Self, Self, Ordering, Ordering) {
1149        self.sin_cos_prec_round_ref(prec, Nearest)
1150    }
1151
1152    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, rounding both
1153    /// results to the nearest value of the specified precision. The [`Float`] is taken by
1154    /// reference. Two [`Ordering`]s are also returned, indicating whether the rounded sine and
1155    /// cosine are less than, equal to, or greater than the exact values.
1156    ///
1157    /// See [`Float::sin_cos_prec`] and [`Float::sin_cos_prec_round`]; this function behaves the
1158    /// same way.
1159    ///
1160    /// # Panics
1161    /// Panics if `prec` is zero.
1162    ///
1163    /// # Examples
1164    /// ```
1165    /// use malachite_float::Float;
1166    /// use std::cmp::Ordering::*;
1167    ///
1168    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 100).0.sin_cos_prec_ref(5);
1169    /// assert_eq!(s.to_string(), "0.844");
1170    /// assert_eq!(c.to_string(), "0.531");
1171    /// assert_eq!(o_s, Greater);
1172    /// assert_eq!(o_c, Less);
1173    /// ```
1174    #[inline]
1175    pub fn sin_cos_prec_ref(&self, prec: u64) -> (Self, Self, Ordering, Ordering) {
1176        self.sin_cos_prec_round_ref(prec, Nearest)
1177    }
1178
1179    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, rounding both
1180    /// results to the precision of the input and with the specified rounding mode. The [`Float`] is
1181    /// taken by value. Two [`Ordering`]s are also returned, indicating whether the rounded sine and
1182    /// cosine are less than, equal to, or greater than the exact values.
1183    ///
1184    /// See [`Float::sin_cos_prec_round`] for the error bounds, the special cases, overflow and
1185    /// underflow, and the complexity; this function behaves the same way with `prec` equal to the
1186    /// precision of the input.
1187    ///
1188    /// If you want to specify an output precision, consider using [`Float::sin_cos_prec_round`]
1189    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1190    /// [`Float::sin_cos`] instead.
1191    ///
1192    /// # Panics
1193    /// Panics if `rm` is `Exact`, since the sine and cosine of a finite nonzero [`Float`] are never
1194    /// exactly representable.
1195    ///
1196    /// # Examples
1197    /// ```
1198    /// use malachite_base::rounding_modes::RoundingMode::*;
1199    /// use malachite_float::Float;
1200    /// use std::cmp::Ordering::*;
1201    ///
1202    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 5).0.sin_cos_round(Floor);
1203    /// assert_eq!(s.to_string(), "0.812");
1204    /// assert_eq!(c.to_string(), "0.531");
1205    /// assert_eq!(o_s, Less);
1206    /// assert_eq!(o_c, Less);
1207    ///
1208    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 5).0.sin_cos_round(Ceiling);
1209    /// assert_eq!(s.to_string(), "0.844");
1210    /// assert_eq!(c.to_string(), "0.562");
1211    /// assert_eq!(o_s, Greater);
1212    /// assert_eq!(o_c, Greater);
1213    /// ```
1214    #[inline]
1215    pub fn sin_cos_round(self, rm: RoundingMode) -> (Self, Self, Ordering, Ordering) {
1216        let prec = self.significant_bits();
1217        self.sin_cos_prec_round_ref(prec, rm)
1218    }
1219
1220    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, rounding both
1221    /// results to the precision of the input and with the specified rounding mode. The [`Float`] is
1222    /// taken by reference. Two [`Ordering`]s are also returned, indicating whether the rounded sine
1223    /// and cosine are less than, equal to, or greater than the exact values.
1224    ///
1225    /// See [`Float::sin_cos_round`] and [`Float::sin_cos_prec_round`]; this function behaves the
1226    /// same way.
1227    ///
1228    /// # Panics
1229    /// Panics if `rm` is `Exact`, since the sine and cosine of a finite nonzero [`Float`] are never
1230    /// exactly representable.
1231    ///
1232    /// # Examples
1233    /// ```
1234    /// use malachite_base::rounding_modes::RoundingMode::*;
1235    /// use malachite_float::Float;
1236    /// use std::cmp::Ordering::*;
1237    ///
1238    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 5)
1239    ///     .0
1240    ///     .sin_cos_round_ref(Floor);
1241    /// assert_eq!(s.to_string(), "0.812");
1242    /// assert_eq!(c.to_string(), "0.531");
1243    /// assert_eq!(o_s, Less);
1244    /// assert_eq!(o_c, Less);
1245    /// ```
1246    #[inline]
1247    pub fn sin_cos_round_ref(&self, rm: RoundingMode) -> (Self, Self, Ordering, Ordering) {
1248        self.sin_cos_prec_round_ref(self.significant_bits(), rm)
1249    }
1250
1251    /// Replaces a [`Float`] with its sine and writes its cosine to `cos`, rounding both results to
1252    /// the specified precision and with the specified rounding mode. The previous value of `cos` is
1253    /// discarded. Two [`Ordering`]s are returned, indicating whether the rounded sine and cosine
1254    /// are less than, equal to, or greater than the exact values.
1255    ///
1256    /// See [`Float::sin_cos_prec_round`] for the error bounds, the special cases, overflow and
1257    /// underflow, and the complexity; this function behaves the same way.
1258    ///
1259    /// If you know you'll be using `Nearest`, consider using [`Float::sin_cos_prec_assign`]
1260    /// instead. If you know that your target precision is the precision of the input, consider
1261    /// using [`Float::sin_cos_round_assign`] instead. If both of these things are true, consider
1262    /// using [`Float::sin_cos_assign`] instead.
1263    ///
1264    /// # Panics
1265    /// Panics if `rm` is `Exact`, since the sine and cosine of a finite nonzero [`Float`] are never
1266    /// exactly representable, or if `prec` is zero.
1267    ///
1268    /// # Examples
1269    /// ```
1270    /// use malachite_base::num::basic::traits::NaN;
1271    /// use malachite_base::rounding_modes::RoundingMode::*;
1272    /// use malachite_float::Float;
1273    /// use std::cmp::Ordering::*;
1274    ///
1275    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1276    /// let mut c = Float::NAN;
1277    /// assert_eq!(x.sin_cos_prec_round_assign(&mut c, 5, Floor), (Less, Less));
1278    /// assert_eq!(x.to_string(), "0.812");
1279    /// assert_eq!(c.to_string(), "0.531");
1280    /// ```
1281    #[inline]
1282    pub fn sin_cos_prec_round_assign(
1283        &mut self,
1284        cos: &mut Self,
1285        prec: u64,
1286        rm: RoundingMode,
1287    ) -> (Ordering, Ordering) {
1288        let (s, c, o_s, o_c) = self.sin_cos_prec_round_ref(prec, rm);
1289        *self = s;
1290        *cos = c;
1291        (o_s, o_c)
1292    }
1293
1294    /// Replaces a [`Float`] with its sine and writes its cosine to `cos`, rounding both results to
1295    /// the nearest value of the specified precision. The previous value of `cos` is discarded. Two
1296    /// [`Ordering`]s are returned, indicating whether the rounded sine and cosine are less than,
1297    /// equal to, or greater than the exact values.
1298    ///
1299    /// See [`Float::sin_cos_prec`] and [`Float::sin_cos_prec_round`]; this function behaves the
1300    /// same way.
1301    ///
1302    /// # Panics
1303    /// Panics if `prec` is zero.
1304    ///
1305    /// # Examples
1306    /// ```
1307    /// use malachite_base::num::basic::traits::NaN;
1308    /// use malachite_float::Float;
1309    /// use std::cmp::Ordering::*;
1310    ///
1311    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1312    /// let mut c = Float::NAN;
1313    /// assert_eq!(x.sin_cos_prec_assign(&mut c, 5), (Greater, Less));
1314    /// assert_eq!(x.to_string(), "0.844");
1315    /// assert_eq!(c.to_string(), "0.531");
1316    /// ```
1317    #[inline]
1318    pub fn sin_cos_prec_assign(&mut self, cos: &mut Self, prec: u64) -> (Ordering, Ordering) {
1319        self.sin_cos_prec_round_assign(cos, prec, Nearest)
1320    }
1321
1322    /// Replaces a [`Float`] with its sine and writes its cosine to `cos`, rounding both results to
1323    /// the precision of the input and with the specified rounding mode. The previous value of `cos`
1324    /// is discarded. Two [`Ordering`]s are returned, indicating whether the rounded sine and cosine
1325    /// are less than, equal to, or greater than the exact values.
1326    ///
1327    /// See [`Float::sin_cos_round`] and [`Float::sin_cos_prec_round`]; this function behaves the
1328    /// same way.
1329    ///
1330    /// # Panics
1331    /// Panics if `rm` is `Exact`, since the sine and cosine of a finite nonzero [`Float`] are never
1332    /// exactly representable.
1333    ///
1334    /// # Examples
1335    /// ```
1336    /// use malachite_base::num::basic::traits::NaN;
1337    /// use malachite_base::rounding_modes::RoundingMode::*;
1338    /// use malachite_float::Float;
1339    /// use std::cmp::Ordering::*;
1340    ///
1341    /// let mut x = Float::from_unsigned_prec(1u32, 5).0;
1342    /// let mut c = Float::NAN;
1343    /// assert_eq!(x.sin_cos_round_assign(&mut c, Floor), (Less, Less));
1344    /// assert_eq!(x.to_string(), "0.812");
1345    /// assert_eq!(c.to_string(), "0.531");
1346    /// ```
1347    #[inline]
1348    pub fn sin_cos_round_assign(
1349        &mut self,
1350        cos: &mut Self,
1351        rm: RoundingMode,
1352    ) -> (Ordering, Ordering) {
1353        let prec = self.significant_bits();
1354        self.sin_cos_prec_round_assign(cos, prec, rm)
1355    }
1356}
1357
1358impl Float {
1359    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Rational`], together, rounding
1360    /// both results to the specified precision and with the specified rounding mode, and returning
1361    /// the results as [`Float`]s. The [`Rational`] is taken by value. Two [`Ordering`]s are also
1362    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
1363    /// than the exact values.
1364    ///
1365    /// The results are the same as those of [`Float::sin_rational_prec_round`] and
1366    /// [`Float::cos_rational_prec_round`], but the rounding of the input, the argument reduction,
1367    /// and most of the work are shared, so this is faster than the two calls when both values are
1368    /// needed.
1369    ///
1370    /// See [`RoundingMode`] for a description of the possible rounding modes.
1371    ///
1372    /// $$
1373    /// f(x,p,m) = (\sin x+\varepsilon_s, \cos x+\varepsilon_c).
1374    /// $$
1375    /// - If $m$ is not `Nearest`, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin x|\rfloor-p+1}$
1376    ///   and $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos x|\rfloor-p+1}$.
1377    /// - If $m$ is `Nearest`, then $|\varepsilon_s| \leq 2^{\lfloor\log_2 |\sin x|\rfloor-p}$ and
1378    ///   $|\varepsilon_c| \leq 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
1379    ///
1380    /// These bounds do not apply when a result underflows.
1381    ///
1382    /// The outputs have precision `prec`.
1383    ///
1384    /// Special cases:
1385    /// - $f(0,p,m)=(0,1)$.
1386    ///
1387    /// Overflow and underflow:
1388    /// - Since $|\sin x|\leq 1$ and $|\cos x|\leq 1$, the results never overflow.
1389    /// - Each result underflows exactly as [`Float::sin_rational_prec_round`] or
1390    ///   [`Float::cos_rational_prec_round`] does; see those functions for the inputs concerned and
1391    ///   the values returned.
1392    ///
1393    /// If you know you'll be using `Nearest`, consider using [`Float::sin_cos_rational_prec`]
1394    /// instead.
1395    ///
1396    /// # Worst-case complexity
1397    /// $T(n, m, e) = O(n (\log n)^3 \log\log n + (n+m+e) (\log (n+m+e))^2 \log\log (n+m+e))$
1398    ///
1399    /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1400    ///
1401    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1402    /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1403    /// is rounded to a working precision and the [`Float`] sine and cosine taken there together,
1404    /// which for $|x| \geq 2$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n +
1405    /// e$ bits.
1406    ///
1407    /// # Panics
1408    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
1409    /// exactly with the given precision (which is the case for every nonzero input).
1410    ///
1411    /// # Examples
1412    /// ```
1413    /// use malachite_base::rounding_modes::RoundingMode::*;
1414    /// use malachite_float::Float;
1415    /// use malachite_q::Rational;
1416    /// use std::cmp::Ordering::*;
1417    ///
1418    /// let (s, c, o_s, o_c) =
1419    ///     Float::sin_cos_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor);
1420    /// assert_eq!(s.to_string(), "0.562");
1421    /// assert_eq!(c.to_string(), "0.812");
1422    /// assert_eq!(o_s, Less);
1423    /// assert_eq!(o_c, Less);
1424    ///
1425    /// let (s, c, o_s, o_c) =
1426    ///     Float::sin_cos_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1427    /// assert_eq!(s.to_string(), "0.594");
1428    /// assert_eq!(c.to_string(), "0.844");
1429    /// assert_eq!(o_s, Greater);
1430    /// assert_eq!(o_c, Greater);
1431    /// ```
1432    #[inline]
1433    #[allow(clippy::needless_pass_by_value)]
1434    pub fn sin_cos_rational_prec_round(
1435        x: Rational,
1436        prec: u64,
1437        rm: RoundingMode,
1438    ) -> (Self, Self, Ordering, Ordering) {
1439        Self::sin_cos_rational_prec_round_ref(&x, prec, rm)
1440    }
1441
1442    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Rational`], together, rounding
1443    /// both results to the specified precision and with the specified rounding mode, and returning
1444    /// the results as [`Float`]s. The [`Rational`] is taken by reference. Two [`Ordering`]s are
1445    /// also returned, indicating whether the rounded sine and cosine are less than, equal to, or
1446    /// greater than the exact values.
1447    ///
1448    /// See [`Float::sin_cos_rational_prec_round`] for the error bounds, the special cases, overflow
1449    /// and underflow, and the complexity; this function behaves the same way.
1450    ///
1451    /// # Panics
1452    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
1453    /// exactly with the given precision (which is the case for every nonzero input).
1454    ///
1455    /// # Examples
1456    /// ```
1457    /// use malachite_base::rounding_modes::RoundingMode::*;
1458    /// use malachite_float::Float;
1459    /// use malachite_q::Rational;
1460    /// use std::cmp::Ordering::*;
1461    ///
1462    /// let (s, c, o_s, o_c) =
1463    ///     Float::sin_cos_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Floor);
1464    /// assert_eq!(s.to_string(), "0.56464195");
1465    /// assert_eq!(c.to_string(), "0.82533550");
1466    /// assert_eq!(o_s, Less);
1467    /// assert_eq!(o_c, Less);
1468    /// ```
1469    pub fn sin_cos_rational_prec_round_ref(
1470        x: &Rational,
1471        prec: u64,
1472        rm: RoundingMode,
1473    ) -> (Self, Self, Ordering, Ordering) {
1474        assert_ne!(prec, 0);
1475        if *x == 0u32 {
1476            // sin(0) = 0 and cos(0) = 1, exactly
1477            return (Self::ZERO, Self::one_prec(prec), Equal, Equal);
1478        }
1479        sin_cos_rational_helper(x, prec, rm)
1480    }
1481
1482    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Rational`], together, rounding
1483    /// both results to the nearest value of the specified precision, and returning the results as
1484    /// [`Float`]s. The [`Rational`] is taken by value. Two [`Ordering`]s are also returned,
1485    /// indicating whether the rounded sine and cosine are less than, equal to, or greater than the
1486    /// exact values.
1487    ///
1488    /// If a result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1489    /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1490    /// the `Nearest` rounding mode.
1491    ///
1492    /// See [`Float::sin_cos_rational_prec_round`] for the error bounds, the special cases, overflow
1493    /// and underflow, and the complexity; this function behaves the same way with `Nearest`.
1494    ///
1495    /// If you want to use a rounding mode other than `Nearest`, consider using
1496    /// [`Float::sin_cos_rational_prec_round`] instead.
1497    ///
1498    /// # Panics
1499    /// Panics if `prec` is zero.
1500    ///
1501    /// # Examples
1502    /// ```
1503    /// use malachite_float::Float;
1504    /// use malachite_q::Rational;
1505    /// use std::cmp::Ordering::*;
1506    ///
1507    /// let (s, c, o_s, o_c) = Float::sin_cos_rational_prec(Rational::from_unsigneds(3u8, 5), 5);
1508    /// assert_eq!(s.to_string(), "0.562");
1509    /// assert_eq!(c.to_string(), "0.812");
1510    /// assert_eq!(o_s, Less);
1511    /// assert_eq!(o_c, Less);
1512    ///
1513    /// let (s, c, o_s, o_c) = Float::sin_cos_rational_prec(Rational::from_unsigneds(3u8, 5), 20);
1514    /// assert_eq!(s.to_string(), "0.56464291");
1515    /// assert_eq!(c.to_string(), "0.82533550");
1516    /// assert_eq!(o_s, Greater);
1517    /// assert_eq!(o_c, Less);
1518    /// ```
1519    #[inline]
1520    #[allow(clippy::needless_pass_by_value)]
1521    pub fn sin_cos_rational_prec(x: Rational, prec: u64) -> (Self, Self, Ordering, Ordering) {
1522        Self::sin_cos_rational_prec_round_ref(&x, prec, Nearest)
1523    }
1524
1525    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Rational`], together, rounding
1526    /// both results to the nearest value of the specified precision, and returning the results as
1527    /// [`Float`]s. The [`Rational`] is taken by reference. Two [`Ordering`]s are also returned,
1528    /// indicating whether the rounded sine and cosine are less than, equal to, or greater than the
1529    /// exact values.
1530    ///
1531    /// See [`Float::sin_cos_rational_prec`] and [`Float::sin_cos_rational_prec_round`]; this
1532    /// function behaves the same way.
1533    ///
1534    /// # Panics
1535    /// Panics if `prec` is zero.
1536    ///
1537    /// # Examples
1538    /// ```
1539    /// use malachite_float::Float;
1540    /// use malachite_q::Rational;
1541    /// use std::cmp::Ordering::*;
1542    ///
1543    /// let (s, c, o_s, o_c) =
1544    ///     Float::sin_cos_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 5);
1545    /// assert_eq!(s.to_string(), "0.562");
1546    /// assert_eq!(c.to_string(), "0.812");
1547    /// assert_eq!(o_s, Less);
1548    /// assert_eq!(o_c, Less);
1549    /// ```
1550    #[inline]
1551    pub fn sin_cos_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Self, Ordering, Ordering) {
1552        Self::sin_cos_rational_prec_round_ref(x, prec, Nearest)
1553    }
1554}
1555
1556// Computes sin(2 pi q) and cos(2 pi q) for a nonzero `Rational` fraction of a turn q in (-1, 1),
1557// rounded to precision `prec` with rounding mode `rm`. `rm` may be `Exact` only when both results
1558// are exact, that is, when q is a multiple of 1/4. This is the `Float` algorithm with the fraction
1559// of a turn taken directly: since q is exact, only pi and the product are rounded.
1560pub(crate) fn sin_cos_turns_helper(
1561    q: &Rational,
1562    prec: u64,
1563    rm: RoundingMode,
1564) -> (Float, Float, Ordering, Ordering) {
1565    let exp_q = q.floor_log_base_2_abs() + 1;
1566    // for q small, the cosine rounds from 1 alone: |cos(2 pi q) - 1| < 1/2 (2 pi q)^2 < 2^(5 + 2
1567    // EXP(q)); the sine takes its own path, as in the `Float` version
1568    let err = -(exp_q << 1) - 5;
1569    if err > 0 {
1570        let err = u64::exact_from(err);
1571        if err > prec + 1 {
1572            assert_ne!(rm, Exact, "Inexact sin_cos_with_period");
1573            let (s, o_s) = sin_turns_helper(q, prec, rm);
1574            let (c, o_c) = near_one(err, false, prec, rm);
1575            return (s, c, o_s, o_c);
1576        }
1577    }
1578    // The special cases need |q| >= 1/20; only a q with both closed forms is taken from them
1579    if exp_q >= -4
1580        && let Some((s, o_s)) = sin_turns_special_case(q, prec, rm)
1581        && let Some((c, o_c)) = cos_turns_special_case(q, prec, rm)
1582    {
1583        return (s, c, o_s, o_c);
1584    }
1585    // Only the exact cases can be rounded exactly
1586    assert_ne!(rm, Exact, "Inexact sin_cos_with_period");
1587    if exp_q <= SCALED_INPUT_EXPONENT {
1588        // as in the `Float` version, only reachable beyond 2^31 bits of precision
1589        fail_on_untested_path("sin_cos_turns_helper, tiny q");
1590        let (s, o_s) = sin_turns_helper(q, prec, rm);
1591        let (c, o_c) = cos_turns_helper(q, prec, rm);
1592        return (s, c, o_s, o_c);
1593    }
1594    let mut w = prec + prec.ceiling_log_base_2() + 8;
1595    let mut increment = Limb::WIDTH;
1596    let sin_near_zero = exp_q >= -2;
1597    loop {
1598        // t = 2*pi*q * (1 + theta)^3 where |theta| <= 2^-w, from rounding q, pi, and the product
1599        let t = (Float::pi_prec(w).0 << 1u32)
1600            .mul_prec(Float::from_rational_prec_ref(q, w).0, w)
1601            .0;
1602        if let Some(result) = sin_cos_turns_step(&t, w, prec, rm, sin_near_zero, || q.clone()) {
1603            return result;
1604        }
1605        w += increment;
1606        increment = w >> 1;
1607    }
1608}
1609
1610impl Float {
1611    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1612    /// in $u$ths of a turn, together, rounding both results to the specified precision and with the
1613    /// specified rounding mode. The [`Float`] is taken by value. Two [`Ordering`]s are also
1614    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
1615    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
1616    /// function returns a `NaN` it also returns `Equal` for it.
1617    ///
1618    /// The results are the same as those of [`Float::sin_with_period_prec_round`] and
1619    /// [`Float::cos_with_period_prec_round`], but the argument reduction, the computation of $2\pi
1620    /// x/u$, and most of the work are shared, so this is faster than the two calls when both values
1621    /// are needed.
1622    ///
1623    /// See [`RoundingMode`] for a description of the possible rounding modes.
1624    ///
1625    /// $$
1626    /// f(x,u,p,m) = (\sin(2\pi x/u)+\varepsilon_s, \cos(2\pi x/u)+\varepsilon_c).
1627    /// $$
1628    /// - If $x$ is not finite or $u=0$, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or
1629    ///   assumed to be 0.
1630    /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon_s| <
1631    ///   2^{\lfloor\log_2 |\sin(2\pi x/u)|\rfloor-p+1}$ and $|\varepsilon_c| < 2^{\lfloor\log_2
1632    ///   |\cos(2\pi x/u)|\rfloor-p+1}$.
1633    /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon_s| \leq
1634    ///   2^{\lfloor\log_2 |\sin(2\pi x/u)|\rfloor-p}$ and $|\varepsilon_c| \leq 2^{\lfloor\log_2
1635    ///   |\cos(2\pi x/u)|\rfloor-p}$.
1636    ///
1637    /// If the outputs have a precision, it is `prec`.
1638    ///
1639    /// Special cases:
1640    /// - $f(\text{NaN},u,p,m)=(\text{NaN},\text{NaN})$
1641    /// - $f(\pm\infty,u,p,m)=(\text{NaN},\text{NaN})$
1642    /// - $f(x,0,p,m)=(\text{NaN},\text{NaN})$
1643    /// - $f(\pm0.0,u,p,m)=(\pm0.0,1.0)$
1644    /// - If $x/u$ is a multiple of $1/4$, both results are exact: the sine is $0.0$ with the sign
1645    ///   of $x$, $1$, or $-1$, and the cosine is $1$, $0.0$, or $-1$, as for
1646    ///   [`Float::sin_with_period_prec_round`] and [`Float::cos_with_period_prec_round`].
1647    ///
1648    /// When $x/u$ in lowest terms has denominator 3, 6, 8, or 12, one result is exactly $\pm1/2$ or
1649    /// both are $\pm\sqrt2/2$, and the other is $\pm\sqrt3/2$; these are computed from a single
1650    /// correctly rounded constant rather than from $\pi$ and a sine and cosine, which is far
1651    /// faster. (A fifth, tenth, or twentieth of a turn has a closed form for only one of the two,
1652    /// and is computed like any other input.)
1653    ///
1654    /// Overflow and underflow:
1655    /// - Since $|\sin(2\pi x/u)|\leq 1$ and $|\cos(2\pi x/u)|\leq 1$, the results never overflow.
1656    /// - Each result underflows exactly as [`Float::sin_with_period_prec_round`] or
1657    ///   [`Float::cos_with_period_prec_round`] does: the sine for $x/u$ within $2^{-2^{30}}$ of a
1658    ///   multiple of $1/2$ without being one, or for an $x$ so small that $2\pi x/u$ is below
1659    ///   $2^{-2^{30}}$, and the cosine for $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$
1660    ///   without being one, which takes more than $2^{30}$ bits of precision. See those functions
1661    ///   for the values returned.
1662    ///
1663    /// If you know you'll be using `Nearest`, consider using [`Float::sin_cos_with_period_prec`]
1664    /// instead. If you know that your target precision is the precision of the input, consider
1665    /// using [`Float::sin_cos_with_period_round`] instead.
1666    ///
1667    /// # Worst-case complexity
1668    /// $T(n, m, e) = O(n (\log n)^3 \log\log n + (n+m+e) (\log (n+m+e))^2 \log\log (n+m+e))$
1669    ///
1670    /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1671    ///
1672    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1673    /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1674    /// a negative one): the argument is reduced modulo $u$ exactly, and the sine and cosine of
1675    /// $2\pi x/u$ are then taken together at a working precision of about $n + e$ bits, which needs
1676    /// $\pi$ to that many bits.
1677    ///
1678    /// # Panics
1679    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
1680    /// exactly with the given precision (which is the case unless $x/u$ is a multiple of $1/4$, or
1681    /// $x$ is zero or not finite, or $u$ is zero).
1682    ///
1683    /// # Examples
1684    /// ```
1685    /// use malachite_base::num::basic::traits::One;
1686    /// use malachite_base::rounding_modes::RoundingMode::*;
1687    /// use malachite_float::Float;
1688    /// use std::cmp::Ordering::*;
1689    ///
1690    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec_round(7, 10, Floor);
1691    /// assert_eq!(s.to_string(), "0.78125");
1692    /// assert_eq!(c.to_string(), "0.62305");
1693    /// assert_eq!(o_s, Less);
1694    /// assert_eq!(o_c, Less);
1695    ///
1696    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec_round(7, 10, Ceiling);
1697    /// assert_eq!(s.to_string(), "0.78223");
1698    /// assert_eq!(c.to_string(), "0.62402");
1699    /// assert_eq!(o_s, Greater);
1700    /// assert_eq!(o_c, Greater);
1701    ///
1702    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec_round(7, 10, Nearest);
1703    /// assert_eq!(s.to_string(), "0.78223");
1704    /// assert_eq!(c.to_string(), "0.62305");
1705    /// assert_eq!(o_s, Greater);
1706    /// assert_eq!(o_c, Less);
1707    ///
1708    /// // a quarter turn is exact
1709    /// let (s, c, o_s, o_c) = Float::from(90u32).sin_cos_with_period_prec_round(360, 10, Exact);
1710    /// assert_eq!(s.to_string(), "1.0000");
1711    /// assert_eq!(c.to_string(), "0.0");
1712    /// assert_eq!(o_s, Equal);
1713    /// assert_eq!(o_c, Equal);
1714    ///
1715    /// // a twelfth of a turn: 1/2 exactly, and sqrt(3)/2
1716    /// let (s, c, o_s, o_c) = Float::from(30u32).sin_cos_with_period_prec_round(360, 10, Nearest);
1717    /// assert_eq!(s.to_string(), "0.50000");
1718    /// assert_eq!(c.to_string(), "0.86621");
1719    /// assert_eq!(o_s, Equal);
1720    /// assert_eq!(o_c, Greater);
1721    /// ```
1722    #[inline]
1723    pub fn sin_cos_with_period_prec_round(
1724        self,
1725        u: u64,
1726        prec: u64,
1727        rm: RoundingMode,
1728    ) -> (Self, Self, Ordering, Ordering) {
1729        self.sin_cos_with_period_prec_round_ref(u, prec, rm)
1730    }
1731
1732    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1733    /// in $u$ths of a turn, together, rounding both results to the specified precision and with the
1734    /// specified rounding mode. The [`Float`] is taken by reference. Two [`Ordering`]s are also
1735    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
1736    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
1737    /// function returns a `NaN` it also returns `Equal` for it.
1738    ///
1739    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special cases,
1740    /// overflow and underflow, and the complexity; this function behaves the same way.
1741    ///
1742    /// # Panics
1743    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
1744    /// exactly with the given precision (which is the case unless $x/u$ is a multiple of $1/4$, or
1745    /// $x$ is zero or not finite, or $u$ is zero).
1746    ///
1747    /// # Examples
1748    /// ```
1749    /// use malachite_base::num::basic::traits::One;
1750    /// use malachite_base::rounding_modes::RoundingMode::*;
1751    /// use malachite_float::Float;
1752    /// use std::cmp::Ordering::*;
1753    ///
1754    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec_round_ref(7, 10, Floor);
1755    /// assert_eq!(s.to_string(), "0.78125");
1756    /// assert_eq!(c.to_string(), "0.62305");
1757    /// assert_eq!(o_s, Less);
1758    /// assert_eq!(o_c, Less);
1759    ///
1760    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec_round_ref(7, 10, Ceiling);
1761    /// assert_eq!(s.to_string(), "0.78223");
1762    /// assert_eq!(c.to_string(), "0.62402");
1763    /// assert_eq!(o_s, Greater);
1764    /// assert_eq!(o_c, Greater);
1765    /// ```
1766    pub fn sin_cos_with_period_prec_round_ref(
1767        &self,
1768        u: u64,
1769        prec: u64,
1770        rm: RoundingMode,
1771    ) -> (Self, Self, Ordering, Ordering) {
1772        assert_ne!(prec, 0);
1773        match &self.0 {
1774            // for u=0, return NaN
1775            _ if u == 0 => (Self::NAN, Self::NAN, Equal, Equal),
1776            NaN | Infinity { .. } => (Self::NAN, Self::NAN, Equal, Equal),
1777            // x is zero: sin(±0) = ±0 and cos(±0) = 1
1778            Zero { .. } => (self.clone(), Self::one_prec(prec), Equal, Equal),
1779            Finite { .. } => sin_cos_with_period_prec_round_normal_ref(self, u, prec, rm),
1780        }
1781    }
1782
1783    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1784    /// in $u$ths of a turn, together, rounding both results to the nearest value of the specified
1785    /// precision. The [`Float`] is taken by value. Two [`Ordering`]s are also returned, indicating
1786    /// whether the rounded sine and cosine are less than, equal to, or greater than the exact
1787    /// values. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1788    /// a `NaN` it also returns `Equal` for it.
1789    ///
1790    /// If a result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1791    /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1792    /// the `Nearest` rounding mode.
1793    ///
1794    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special cases,
1795    /// overflow and underflow, and the complexity; this function behaves the same way with
1796    /// `Nearest`.
1797    ///
1798    /// If you want to use a rounding mode other than `Nearest`, consider using
1799    /// [`Float::sin_cos_with_period_prec_round`] instead. If you know that your target precision is
1800    /// the precision of the input, consider using [`Float::sin_cos_with_period_round`] with
1801    /// `Nearest` instead.
1802    ///
1803    /// # Panics
1804    /// Panics if `prec` is zero.
1805    ///
1806    /// # Examples
1807    /// ```
1808    /// use malachite_base::num::basic::traits::One;
1809    /// use malachite_float::Float;
1810    /// use std::cmp::Ordering::*;
1811    ///
1812    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec(7, 10);
1813    /// assert_eq!(s.to_string(), "0.78223");
1814    /// assert_eq!(c.to_string(), "0.62305");
1815    /// assert_eq!(o_s, Greater);
1816    /// assert_eq!(o_c, Less);
1817    ///
1818    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec(360, 53);
1819    /// assert_eq!(s.to_string(), "0.017452406437283512");
1820    /// assert_eq!(c.to_string(), "0.99984769515639127");
1821    /// assert_eq!(o_s, Less);
1822    /// assert_eq!(o_c, Greater);
1823    ///
1824    /// // an eighth of a turn: sqrt(2)/2 for both
1825    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec(8, 10);
1826    /// assert_eq!(s.to_string(), "0.70703");
1827    /// assert_eq!(c.to_string(), "0.70703");
1828    /// assert_eq!(o_s, Less);
1829    /// assert_eq!(o_c, Less);
1830    /// ```
1831    #[inline]
1832    pub fn sin_cos_with_period_prec(self, u: u64, prec: u64) -> (Self, Self, Ordering, Ordering) {
1833        self.sin_cos_with_period_prec_round_ref(u, prec, Nearest)
1834    }
1835
1836    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1837    /// in $u$ths of a turn, together, rounding both results to the nearest value of the specified
1838    /// precision. The [`Float`] is taken by reference. Two [`Ordering`]s are also returned,
1839    /// indicating whether the rounded sine and cosine are less than, equal to, or greater than the
1840    /// exact values. Although `NaN`s are not comparable to any [`Float`], whenever this function
1841    /// returns a `NaN` it also returns `Equal` for it.
1842    ///
1843    /// See [`Float::sin_cos_with_period_prec`] and [`Float::sin_cos_with_period_prec_round`]; this
1844    /// function behaves the same way.
1845    ///
1846    /// # Panics
1847    /// Panics if `prec` is zero.
1848    ///
1849    /// # Examples
1850    /// ```
1851    /// use malachite_base::num::basic::traits::One;
1852    /// use malachite_float::Float;
1853    /// use std::cmp::Ordering::*;
1854    ///
1855    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_with_period_prec_ref(7, 10);
1856    /// assert_eq!(s.to_string(), "0.78223");
1857    /// assert_eq!(c.to_string(), "0.62305");
1858    /// assert_eq!(o_s, Greater);
1859    /// assert_eq!(o_c, Less);
1860    /// ```
1861    #[inline]
1862    pub fn sin_cos_with_period_prec_ref(
1863        &self,
1864        u: u64,
1865        prec: u64,
1866    ) -> (Self, Self, Ordering, Ordering) {
1867        self.sin_cos_with_period_prec_round_ref(u, prec, Nearest)
1868    }
1869
1870    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1871    /// in $u$ths of a turn, together, rounding both results to the precision of the input and with
1872    /// the specified rounding mode. The [`Float`] is taken by value. Two [`Ordering`]s are also
1873    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
1874    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
1875    /// function returns a `NaN` it also returns `Equal` for it.
1876    ///
1877    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special cases,
1878    /// overflow and underflow, and the complexity; this function behaves the same way with `prec`
1879    /// equal to the precision of the input.
1880    ///
1881    /// If you want to specify an output precision, consider using
1882    /// [`Float::sin_cos_with_period_prec_round`] instead. If you know you'll be using the `Nearest`
1883    /// rounding mode, consider using [`Float::sin_cos_with_period_prec`] with the precision of the
1884    /// input instead.
1885    ///
1886    /// # Panics
1887    /// Panics if `rm` is `Exact` but the results cannot be represented exactly with the precision
1888    /// of the input (which is the case unless $x/u$ is a multiple of $1/4$, or $x$ is zero or not
1889    /// finite, or $u$ is zero).
1890    ///
1891    /// # Examples
1892    /// ```
1893    /// use malachite_base::rounding_modes::RoundingMode::*;
1894    /// use malachite_float::Float;
1895    /// use std::cmp::Ordering::*;
1896    ///
1897    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 10)
1898    ///     .0
1899    ///     .sin_cos_with_period_round(7, Floor);
1900    /// assert_eq!(s.to_string(), "0.78125");
1901    /// assert_eq!(c.to_string(), "0.62305");
1902    /// assert_eq!(o_s, Less);
1903    /// assert_eq!(o_c, Less);
1904    ///
1905    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 10)
1906    ///     .0
1907    ///     .sin_cos_with_period_round(7, Ceiling);
1908    /// assert_eq!(s.to_string(), "0.78223");
1909    /// assert_eq!(c.to_string(), "0.62402");
1910    /// assert_eq!(o_s, Greater);
1911    /// assert_eq!(o_c, Greater);
1912    /// ```
1913    #[inline]
1914    pub fn sin_cos_with_period_round(
1915        self,
1916        u: u64,
1917        rm: RoundingMode,
1918    ) -> (Self, Self, Ordering, Ordering) {
1919        let prec = self.significant_bits();
1920        self.sin_cos_with_period_prec_round_ref(u, prec, rm)
1921    }
1922
1923    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1924    /// in $u$ths of a turn, together, rounding both results to the precision of the input and with
1925    /// the specified rounding mode. The [`Float`] is taken by reference. Two [`Ordering`]s are also
1926    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
1927    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
1928    /// function returns a `NaN` it also returns `Equal` for it.
1929    ///
1930    /// See [`Float::sin_cos_with_period_round`] and [`Float::sin_cos_with_period_prec_round`]; this
1931    /// function behaves the same way.
1932    ///
1933    /// # Panics
1934    /// Panics if `rm` is `Exact` but the results cannot be represented exactly with the precision
1935    /// of the input (which is the case unless $x/u$ is a multiple of $1/4$, or $x$ is zero or not
1936    /// finite, or $u$ is zero).
1937    ///
1938    /// # Examples
1939    /// ```
1940    /// use malachite_base::rounding_modes::RoundingMode::*;
1941    /// use malachite_float::Float;
1942    /// use std::cmp::Ordering::*;
1943    ///
1944    /// let (s, c, o_s, o_c) = Float::from_unsigned_prec(1u32, 10)
1945    ///     .0
1946    ///     .sin_cos_with_period_round_ref(7, Floor);
1947    /// assert_eq!(s.to_string(), "0.78125");
1948    /// assert_eq!(c.to_string(), "0.62305");
1949    /// assert_eq!(o_s, Less);
1950    /// assert_eq!(o_c, Less);
1951    /// ```
1952    #[inline]
1953    pub fn sin_cos_with_period_round_ref(
1954        &self,
1955        u: u64,
1956        rm: RoundingMode,
1957    ) -> (Self, Self, Ordering, Ordering) {
1958        self.sin_cos_with_period_prec_round_ref(u, self.significant_bits(), rm)
1959    }
1960
1961    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1962    /// in $u$ths of a turn (so that `u = 360` is degrees), together, rounding both results to the
1963    /// precision of the input and to the nearest [`Float`]s. The [`Float`] is taken by value.
1964    ///
1965    /// If either result is equidistant from two [`Float`]s with the precision of the input, the
1966    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1967    /// description of the `Nearest` rounding mode.
1968    ///
1969    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special and
1970    /// closed-form cases, overflow and underflow, and the complexity; this function behaves the
1971    /// same way with `prec` equal to the precision of the input and `rm` equal to `Nearest`.
1972    ///
1973    /// If you want to use a rounding mode other than `Nearest`, consider using
1974    /// [`Float::sin_cos_with_period_round`] instead. If you want to specify an output precision,
1975    /// consider using [`Float::sin_cos_with_period_prec`]. If you want both of these things,
1976    /// consider using [`Float::sin_cos_with_period_prec_round`].
1977    ///
1978    /// # Examples
1979    /// ```
1980    /// use malachite_float::Float;
1981    ///
1982    /// let (s, c) = Float::from_unsigned_prec(1u32, 10).0.sin_cos_with_period(7);
1983    /// assert_eq!(s.to_string(), "0.78223");
1984    /// assert_eq!(c.to_string(), "0.62305");
1985    /// ```
1986    #[inline]
1987    pub fn sin_cos_with_period(self, u: u64) -> (Self, Self) {
1988        let prec = self.significant_bits();
1989        let (s, c, _, _) = self.sin_cos_with_period_prec(u, prec);
1990        (s, c)
1991    }
1992
1993    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
1994    /// in $u$ths of a turn (so that `u = 360` is degrees), together, rounding both results to the
1995    /// precision of the input and to the nearest [`Float`]s. The [`Float`] is taken by reference.
1996    ///
1997    /// If either result is equidistant from two [`Float`]s with the precision of the input, the
1998    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1999    /// description of the `Nearest` rounding mode.
2000    ///
2001    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special and
2002    /// closed-form cases, overflow and underflow, and the complexity; this function behaves the
2003    /// same way with `prec` equal to the precision of the input and `rm` equal to `Nearest`.
2004    ///
2005    /// If you want to use a rounding mode other than `Nearest`, consider using
2006    /// [`Float::sin_cos_with_period_round_ref`] instead. If you want to specify an output
2007    /// precision, consider using [`Float::sin_cos_with_period_prec_ref`]. If you want both of these
2008    /// things, consider using [`Float::sin_cos_with_period_prec_round_ref`].
2009    ///
2010    /// # Examples
2011    /// ```
2012    /// use malachite_float::Float;
2013    ///
2014    /// let (s, c) = (&Float::from_unsigned_prec(1u32, 10).0).sin_cos_with_period_ref(7);
2015    /// assert_eq!(s.to_string(), "0.78223");
2016    /// assert_eq!(c.to_string(), "0.62305");
2017    /// ```
2018    #[inline]
2019    pub fn sin_cos_with_period_ref(&self, u: u64) -> (Self, Self) {
2020        let (s, c, _, _) = self.sin_cos_with_period_prec_ref(u, self.significant_bits());
2021        (s, c)
2022    }
2023
2024    /// Replaces a [`Float`] measured in $u$ths of a turn with its sine and writes its cosine to
2025    /// `cos`, rounding both results to the specified precision and with the specified rounding
2026    /// mode. The previous value of `cos` is discarded. Two [`Ordering`]s are returned, indicating
2027    /// whether the rounded sine and cosine are less than, equal to, or greater than the exact
2028    /// values. Although `NaN`s are not comparable to any [`Float`], whenever this function sets a
2029    /// `NaN` it also returns `Equal` for it.
2030    ///
2031    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special cases,
2032    /// overflow and underflow, and the complexity; this function behaves the same way.
2033    ///
2034    /// If you know you'll be using `Nearest`, consider using
2035    /// [`Float::sin_cos_with_period_prec_assign`] instead. If you know that your target precision
2036    /// is the precision of the input, consider using [`Float::sin_cos_with_period_round_assign`]
2037    /// instead.
2038    ///
2039    /// # Panics
2040    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2041    /// exactly with the given precision (which is the case unless $x/u$ is a multiple of $1/4$, or
2042    /// $x$ is zero or not finite, or $u$ is zero).
2043    ///
2044    /// # Examples
2045    /// ```
2046    /// use malachite_base::num::basic::traits::{NaN, One};
2047    /// use malachite_base::rounding_modes::RoundingMode::*;
2048    /// use malachite_float::Float;
2049    /// use std::cmp::Ordering::*;
2050    ///
2051    /// let mut x = Float::ONE;
2052    /// let mut c = Float::NAN;
2053    /// assert_eq!(
2054    ///     x.sin_cos_with_period_prec_round_assign(&mut c, 7, 10, Floor),
2055    ///     (Less, Less)
2056    /// );
2057    /// assert_eq!(x.to_string(), "0.78125");
2058    /// assert_eq!(c.to_string(), "0.62305");
2059    /// ```
2060    #[inline]
2061    pub fn sin_cos_with_period_prec_round_assign(
2062        &mut self,
2063        cos: &mut Self,
2064        u: u64,
2065        prec: u64,
2066        rm: RoundingMode,
2067    ) -> (Ordering, Ordering) {
2068        let (s, c, o_s, o_c) = self.sin_cos_with_period_prec_round_ref(u, prec, rm);
2069        *self = s;
2070        *cos = c;
2071        (o_s, o_c)
2072    }
2073
2074    /// Replaces a [`Float`] measured in $u$ths of a turn with its sine and writes its cosine to
2075    /// `cos`, rounding both results to the nearest value of the specified precision. The previous
2076    /// value of `cos` is discarded. Two [`Ordering`]s are returned, indicating whether the rounded
2077    /// sine and cosine are less than, equal to, or greater than the exact values. Although `NaN`s
2078    /// are not comparable to any [`Float`], whenever this function sets a `NaN` it also returns
2079    /// `Equal` for it.
2080    ///
2081    /// See [`Float::sin_cos_with_period_prec`] and [`Float::sin_cos_with_period_prec_round`]; this
2082    /// function behaves the same way.
2083    ///
2084    /// # Panics
2085    /// Panics if `prec` is zero.
2086    ///
2087    /// # Examples
2088    /// ```
2089    /// use malachite_base::num::basic::traits::{NaN, One};
2090    /// use malachite_float::Float;
2091    /// use std::cmp::Ordering::*;
2092    ///
2093    /// let mut x = Float::ONE;
2094    /// let mut c = Float::NAN;
2095    /// assert_eq!(
2096    ///     x.sin_cos_with_period_prec_assign(&mut c, 7, 10),
2097    ///     (Greater, Less)
2098    /// );
2099    /// assert_eq!(x.to_string(), "0.78223");
2100    /// assert_eq!(c.to_string(), "0.62305");
2101    /// ```
2102    #[inline]
2103    pub fn sin_cos_with_period_prec_assign(
2104        &mut self,
2105        cos: &mut Self,
2106        u: u64,
2107        prec: u64,
2108    ) -> (Ordering, Ordering) {
2109        self.sin_cos_with_period_prec_round_assign(cos, u, prec, Nearest)
2110    }
2111
2112    /// Replaces a [`Float`] measured in $u$ths of a turn with its sine and writes its cosine to
2113    /// `cos`, rounding both results to the precision of the input and with the specified rounding
2114    /// mode. The previous value of `cos` is discarded. Two [`Ordering`]s are returned, indicating
2115    /// whether the rounded sine and cosine are less than, equal to, or greater than the exact
2116    /// values. Although `NaN`s are not comparable to any [`Float`], whenever this function sets a
2117    /// `NaN` it also returns `Equal` for it.
2118    ///
2119    /// See [`Float::sin_cos_with_period_round`] and [`Float::sin_cos_with_period_prec_round`]; this
2120    /// function behaves the same way.
2121    ///
2122    /// # Panics
2123    /// Panics if `rm` is `Exact` but the results cannot be represented exactly with the precision
2124    /// of the input (which is the case unless $x/u$ is a multiple of $1/4$, or $x$ is zero or not
2125    /// finite, or $u$ is zero).
2126    ///
2127    /// # Examples
2128    /// ```
2129    /// use malachite_base::num::basic::traits::NaN;
2130    /// use malachite_base::rounding_modes::RoundingMode::*;
2131    /// use malachite_float::Float;
2132    /// use std::cmp::Ordering::*;
2133    ///
2134    /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
2135    /// let mut c = Float::NAN;
2136    /// assert_eq!(
2137    ///     x.sin_cos_with_period_round_assign(&mut c, 7, Floor),
2138    ///     (Less, Less)
2139    /// );
2140    /// assert_eq!(x.to_string(), "0.78125");
2141    /// assert_eq!(c.to_string(), "0.62305");
2142    /// ```
2143    #[inline]
2144    pub fn sin_cos_with_period_round_assign(
2145        &mut self,
2146        cos: &mut Self,
2147        u: u64,
2148        rm: RoundingMode,
2149    ) -> (Ordering, Ordering) {
2150        let prec = self.significant_bits();
2151        self.sin_cos_with_period_prec_round_assign(cos, u, prec, rm)
2152    }
2153
2154    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Float`] measured
2155    /// in $u$ths of a turn (so that `u = 360` is degrees), together, rounding both results to the
2156    /// precision of the input and to the nearest [`Float`]s. The [`Float`] is replaced by the sine,
2157    /// and the cosine is written to `cos`, whose previous value is discarded.
2158    ///
2159    /// If either result is equidistant from two [`Float`]s with the precision of the input, the
2160    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2161    /// description of the `Nearest` rounding mode.
2162    ///
2163    /// See [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special and
2164    /// closed-form cases, overflow and underflow, and the complexity; this function behaves the
2165    /// same way with `prec` equal to the precision of the input and `rm` equal to `Nearest`.
2166    ///
2167    /// If you want to use a rounding mode other than `Nearest`, consider using
2168    /// [`Float::sin_cos_with_period_round_assign`] instead. If you want to specify an output
2169    /// precision, consider using [`Float::sin_cos_with_period_prec_assign`]. If you want both of
2170    /// these things, consider using [`Float::sin_cos_with_period_prec_round_assign`].
2171    ///
2172    /// # Examples
2173    /// ```
2174    /// use malachite_base::num::basic::traits::NaN;
2175    /// use malachite_float::Float;
2176    ///
2177    /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
2178    /// let mut c = Float::NAN;
2179    /// x.sin_cos_with_period_assign(&mut c, 7);
2180    /// assert_eq!(x.to_string(), "0.78223");
2181    /// assert_eq!(c.to_string(), "0.62305");
2182    /// ```
2183    #[inline]
2184    pub fn sin_cos_with_period_assign(&mut self, cos: &mut Self, u: u64) {
2185        let prec = self.significant_bits();
2186        self.sin_cos_with_period_prec_assign(cos, u, prec);
2187    }
2188}
2189
2190impl Float {
2191    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Rational`]
2192    /// measured in $u$ths of a turn, together, rounding both results to the specified precision and
2193    /// with the specified rounding mode, and returning the results as [`Float`]s. The [`Rational`]
2194    /// is taken by value. Two [`Ordering`]s are also returned, indicating whether the rounded sine
2195    /// and cosine are less than, equal to, or greater than the exact values. Although `NaN`s are
2196    /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
2197    /// `Equal` for it.
2198    ///
2199    /// The results are the same as those of [`Float::sin_with_period_rational_prec_round`] and
2200    /// [`Float::cos_with_period_rational_prec_round`], but the reduction of the fraction of a turn,
2201    /// the computation of $2\pi x/u$, and most of the work are shared, so this is faster than the
2202    /// two calls when both values are needed.
2203    ///
2204    /// See [`RoundingMode`] for a description of the possible rounding modes.
2205    ///
2206    /// $$
2207    /// f(x,u,p,m) = (\sin(2\pi x/u)+\varepsilon_s, \cos(2\pi x/u)+\varepsilon_c).
2208    /// $$
2209    /// - If $u=0$, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or assumed to be 0.
2210    /// - If $u\neq 0$ and $m$ is not `Nearest`, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin(2\pi
2211    ///   x/u)|\rfloor-p+1}$ and $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$.
2212    /// - If $u\neq 0$ and $m$ is `Nearest`, then $|\varepsilon_s| \leq 2^{\lfloor\log_2 |\sin(2\pi
2213    ///   x/u)|\rfloor-p}$ and $|\varepsilon_c| \leq 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$.
2214    ///
2215    /// If the outputs have a precision, it is `prec`.
2216    ///
2217    /// Special cases:
2218    /// - $f(x,0,p,m)=(\text{NaN},\text{NaN})$
2219    /// - $f(0,u,p,m)=(0,1)$
2220    /// - If $x/u$ is a multiple of $1/4$, both results are exact: the sine is $0.0$ with the sign
2221    ///   of $x$, $1$, or $-1$, and the cosine is $1$, $0.0$, or $-1$, as for
2222    ///   [`Float::sin_with_period_rational_prec_round`] and
2223    ///   [`Float::cos_with_period_rational_prec_round`].
2224    ///
2225    /// When $x/u$ in lowest terms has denominator 3, 6, 8, or 12, one result is exactly $\pm1/2$ or
2226    /// both are $\pm\sqrt2/2$, and the other is $\pm\sqrt3/2$; these are computed from a single
2227    /// correctly rounded constant rather than from $\pi$ and a sine and cosine, which is far
2228    /// faster. (A fifth, tenth, or twentieth of a turn has a closed form for only one of the two,
2229    /// and is computed like any other input.)
2230    ///
2231    /// Overflow and underflow:
2232    /// - Since $|\sin(2\pi x/u)|\leq 1$ and $|\cos(2\pi x/u)|\leq 1$, the results never overflow.
2233    /// - Each result underflows exactly as [`Float::sin_with_period_rational_prec_round`] or
2234    ///   [`Float::cos_with_period_rational_prec_round`] does: the sine for $x/u$ within
2235    ///   $2^{-2^{30}}$ of a multiple of $1/2$ without being one, or for an $x/u$ so small that
2236    ///   $2\pi x/u$ is below $2^{-2^{30}}$, and the cosine for $x/u$ within $2^{-2^{30}}$ of an odd
2237    ///   multiple of $1/4$ without being one, which takes a denominator of more than $2^{30}$ bits.
2238    ///   See those functions for the values returned.
2239    ///
2240    /// If you know you'll be using `Nearest`, consider using
2241    /// [`Float::sin_cos_with_period_rational_prec`] instead.
2242    ///
2243    /// # Worst-case complexity
2244    /// $T(n, m) = O(n (\log n)^3 \log\log n + (n+m) (\log (n+m))^2 \log\log (n+m))$
2245    ///
2246    /// $M(n, m) = O((n+m) \log (n+m))$
2247    ///
2248    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2249    /// `x.significant_bits()`: the fraction of a turn is reduced modulo 1 exactly, so only its size
2250    /// and the precision drive the cost, not the magnitude of $x$.
2251    ///
2252    /// # Panics
2253    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2254    /// exactly with the given precision (which is the case unless $x/u$ is a multiple of $1/4$, or
2255    /// $x$ or $u$ is zero).
2256    ///
2257    /// # Examples
2258    /// ```
2259    /// use malachite_base::num::basic::traits::One;
2260    /// use malachite_base::rounding_modes::RoundingMode::*;
2261    /// use malachite_float::Float;
2262    /// use malachite_q::Rational;
2263    /// use std::cmp::Ordering::*;
2264    ///
2265    /// let (s, c, o_s, o_c) =
2266    ///     Float::sin_cos_with_period_rational_prec_round(Rational::ONE, 7, 10, Floor);
2267    /// assert_eq!(s.to_string(), "0.78125");
2268    /// assert_eq!(c.to_string(), "0.62305");
2269    /// assert_eq!(o_s, Less);
2270    /// assert_eq!(o_c, Less);
2271    ///
2272    /// let (s, c, o_s, o_c) =
2273    ///     Float::sin_cos_with_period_rational_prec_round(Rational::ONE, 7, 10, Ceiling);
2274    /// assert_eq!(s.to_string(), "0.78223");
2275    /// assert_eq!(c.to_string(), "0.62402");
2276    /// assert_eq!(o_s, Greater);
2277    /// assert_eq!(o_c, Greater);
2278    ///
2279    /// // a quarter turn is exact
2280    /// let (s, c, o_s, o_c) = Float::sin_cos_with_period_rational_prec_round(
2281    ///     Rational::from_unsigneds(1u8, 4),
2282    ///     1,
2283    ///     10,
2284    ///     Exact,
2285    /// );
2286    /// assert_eq!(s.to_string(), "1.0000");
2287    /// assert_eq!(c.to_string(), "0.0");
2288    /// assert_eq!(o_s, Equal);
2289    /// assert_eq!(o_c, Equal);
2290    ///
2291    /// // a twelfth of a turn: 1/2 exactly, and sqrt(3)/2
2292    /// let (s, c, o_s, o_c) = Float::sin_cos_with_period_rational_prec_round(
2293    ///     Rational::from_unsigneds(1u8, 12),
2294    ///     1,
2295    ///     10,
2296    ///     Nearest,
2297    /// );
2298    /// assert_eq!(s.to_string(), "0.50000");
2299    /// assert_eq!(c.to_string(), "0.86621");
2300    /// assert_eq!(o_s, Equal);
2301    /// assert_eq!(o_c, Greater);
2302    /// ```
2303    #[inline]
2304    #[allow(clippy::needless_pass_by_value)]
2305    pub fn sin_cos_with_period_rational_prec_round(
2306        x: Rational,
2307        u: u64,
2308        prec: u64,
2309        rm: RoundingMode,
2310    ) -> (Self, Self, Ordering, Ordering) {
2311        Self::sin_cos_with_period_rational_prec_round_ref(&x, u, prec, rm)
2312    }
2313
2314    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Rational`]
2315    /// measured in $u$ths of a turn, together, rounding both results to the specified precision and
2316    /// with the specified rounding mode, and returning the results as [`Float`]s. The [`Rational`]
2317    /// is taken by reference. Two [`Ordering`]s are also returned, indicating whether the rounded
2318    /// sine and cosine are less than, equal to, or greater than the exact values. Although `NaN`s
2319    /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
2320    /// `Equal` for it.
2321    ///
2322    /// See [`Float::sin_cos_with_period_rational_prec_round`] for the error bounds, the special
2323    /// cases, overflow and underflow, and the complexity; this function behaves the same way.
2324    ///
2325    /// # Panics
2326    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2327    /// exactly with the given precision (which is the case unless $x/u$ is a multiple of $1/4$, or
2328    /// $x$ or $u$ is zero).
2329    ///
2330    /// # Examples
2331    /// ```
2332    /// use malachite_base::num::basic::traits::One;
2333    /// use malachite_base::rounding_modes::RoundingMode::*;
2334    /// use malachite_float::Float;
2335    /// use malachite_q::Rational;
2336    /// use std::cmp::Ordering::*;
2337    ///
2338    /// let (s, c, o_s, o_c) =
2339    ///     Float::sin_cos_with_period_rational_prec_round_ref(&Rational::ONE, 7, 10, Floor);
2340    /// assert_eq!(s.to_string(), "0.78125");
2341    /// assert_eq!(c.to_string(), "0.62305");
2342    /// assert_eq!(o_s, Less);
2343    /// assert_eq!(o_c, Less);
2344    ///
2345    /// // an eighth of a turn: sqrt(2)/2 for both
2346    /// let (s, c, o_s, o_c) = Float::sin_cos_with_period_rational_prec_round_ref(
2347    ///     &Rational::from_unsigneds(1u8, 8),
2348    ///     1,
2349    ///     10,
2350    ///     Nearest,
2351    /// );
2352    /// assert_eq!(s.to_string(), "0.70703");
2353    /// assert_eq!(c.to_string(), "0.70703");
2354    /// assert_eq!(o_s, Less);
2355    /// assert_eq!(o_c, Less);
2356    /// ```
2357    pub fn sin_cos_with_period_rational_prec_round_ref(
2358        x: &Rational,
2359        u: u64,
2360        prec: u64,
2361        rm: RoundingMode,
2362    ) -> (Self, Self, Ordering, Ordering) {
2363        assert_ne!(prec, 0);
2364        // for u = 0, return NaN
2365        if u == 0 {
2366            return (Self::NAN, Self::NAN, Equal, Equal);
2367        }
2368        // sin(0) = 0 (a `Rational` zero has no sign) and cos(0) = 1
2369        if *x == 0u32 {
2370            return (Self::ZERO, Self::one_prec(prec), Equal, Equal);
2371        }
2372        // q = x/u, reduced to (-1, 1) with the sign of x: both functions have period 1 in q, and a
2373        // multiple of u gives a sine of zero with the sign of x (IEEE 754-2019's sinPi) and a
2374        // cosine of 1
2375        let q = x / Rational::from(u) % Rational::ONE;
2376        if q == 0u32 {
2377            return (
2378                if *x < 0u32 {
2379                    Self::NEGATIVE_ZERO
2380                } else {
2381                    Self::ZERO
2382                },
2383                Self::one_prec(prec),
2384                Equal,
2385                Equal,
2386            );
2387        }
2388        sin_cos_turns_helper(&q, prec, rm)
2389    }
2390
2391    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Rational`]
2392    /// measured in $u$ths of a turn, together, rounding both results to the nearest value of the
2393    /// specified precision, and returning the results as [`Float`]s. The [`Rational`] is taken by
2394    /// value. Two [`Ordering`]s are also returned, indicating whether the rounded sine and cosine
2395    /// are less than, equal to, or greater than the exact values. Although `NaN`s are not
2396    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`
2397    /// for it.
2398    ///
2399    /// If a result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
2400    /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
2401    /// the `Nearest` rounding mode.
2402    ///
2403    /// See [`Float::sin_cos_with_period_rational_prec_round`] for the error bounds, the special
2404    /// cases, overflow and underflow, and the complexity; this function behaves the same way with
2405    /// `Nearest`.
2406    ///
2407    /// If you want to use a rounding mode other than `Nearest`, consider using
2408    /// [`Float::sin_cos_with_period_rational_prec_round`] instead.
2409    ///
2410    /// # Panics
2411    /// Panics if `prec` is zero.
2412    ///
2413    /// # Examples
2414    /// ```
2415    /// use malachite_base::num::basic::traits::One;
2416    /// use malachite_float::Float;
2417    /// use malachite_q::Rational;
2418    /// use std::cmp::Ordering::*;
2419    ///
2420    /// let (s, c, o_s, o_c) = Float::sin_cos_with_period_rational_prec(Rational::ONE, 7, 10);
2421    /// assert_eq!(s.to_string(), "0.78223");
2422    /// assert_eq!(c.to_string(), "0.62305");
2423    /// assert_eq!(o_s, Greater);
2424    /// assert_eq!(o_c, Less);
2425    ///
2426    /// let (s, c, o_s, o_c) = Float::sin_cos_with_period_rational_prec(Rational::ONE, 360, 53);
2427    /// assert_eq!(s.to_string(), "0.017452406437283512");
2428    /// assert_eq!(c.to_string(), "0.99984769515639127");
2429    /// assert_eq!(o_s, Less);
2430    /// assert_eq!(o_c, Greater);
2431    /// ```
2432    #[inline]
2433    #[allow(clippy::needless_pass_by_value)]
2434    pub fn sin_cos_with_period_rational_prec(
2435        x: Rational,
2436        u: u64,
2437        prec: u64,
2438    ) -> (Self, Self, Ordering, Ordering) {
2439        Self::sin_cos_with_period_rational_prec_round_ref(&x, u, prec, Nearest)
2440    }
2441
2442    /// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Rational`]
2443    /// measured in $u$ths of a turn, together, rounding both results to the nearest value of the
2444    /// specified precision, and returning the results as [`Float`]s. The [`Rational`] is taken by
2445    /// reference. Two [`Ordering`]s are also returned, indicating whether the rounded sine and
2446    /// cosine are less than, equal to, or greater than the exact values. Although `NaN`s are not
2447    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`
2448    /// for it.
2449    ///
2450    /// See [`Float::sin_cos_with_period_rational_prec`] and
2451    /// [`Float::sin_cos_with_period_rational_prec_round`]; this function behaves the same way.
2452    ///
2453    /// # Panics
2454    /// Panics if `prec` is zero.
2455    ///
2456    /// # Examples
2457    /// ```
2458    /// use malachite_base::num::basic::traits::One;
2459    /// use malachite_float::Float;
2460    /// use malachite_q::Rational;
2461    /// use std::cmp::Ordering::*;
2462    ///
2463    /// let (s, c, o_s, o_c) = Float::sin_cos_with_period_rational_prec_ref(&Rational::ONE, 7, 10);
2464    /// assert_eq!(s.to_string(), "0.78223");
2465    /// assert_eq!(c.to_string(), "0.62305");
2466    /// assert_eq!(o_s, Greater);
2467    /// assert_eq!(o_c, Less);
2468    /// ```
2469    #[inline]
2470    pub fn sin_cos_with_period_rational_prec_ref(
2471        x: &Rational,
2472        u: u64,
2473        prec: u64,
2474    ) -> (Self, Self, Ordering, Ordering) {
2475        Self::sin_cos_with_period_rational_prec_round_ref(x, u, prec, Nearest)
2476    }
2477}
2478
2479impl Float {
2480    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2481    /// half-turns, together, rounding both results to the specified precision and with the
2482    /// specified rounding mode. The [`Float`] is taken by value. Two [`Ordering`]s are also
2483    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
2484    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
2485    /// function returns a `NaN` it also returns `Equal` for it.
2486    ///
2487    /// This is `sin_cos_with_period` with a period of 2: see
2488    /// [`Float::sin_cos_with_period_prec_round`] for the error bounds, the special and closed-form
2489    /// cases (multiples of $1/2$ give exact pairs from $\pm0.0$ and $\pm1$, and odd multiples of
2490    /// $1/6$, $1/4$, and $1/3$ have closed forms for both), overflow and underflow, and the
2491    /// complexity, with $u = 2$.
2492    ///
2493    /// # Panics
2494    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2495    /// exactly with the given precision.
2496    ///
2497    /// # Examples
2498    /// ```
2499    /// use malachite_base::num::basic::traits::One;
2500    /// use malachite_base::rounding_modes::RoundingMode::*;
2501    /// use malachite_float::Float;
2502    /// use std::cmp::Ordering::*;
2503    ///
2504    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_prec_round(10, Floor);
2505    /// assert_eq!(s.to_string(), "0.30859");
2506    /// assert_eq!(c.to_string(), "0.95020");
2507    /// assert_eq!(o_s, Less);
2508    /// assert_eq!(o_c, Less);
2509    ///
2510    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_prec_round(10, Ceiling);
2511    /// assert_eq!(s.to_string(), "0.30908");
2512    /// assert_eq!(c.to_string(), "0.95117");
2513    /// assert_eq!(o_s, Greater);
2514    /// assert_eq!(o_c, Greater);
2515    ///
2516    /// // a half-turn is exact
2517    /// let (s, c, o_s, o_c) = Float::ONE.sin_cos_pi_prec_round(10, Exact);
2518    /// assert_eq!(s.to_string(), "0.0");
2519    /// assert_eq!(c.to_string(), "-1.0000");
2520    /// assert_eq!(o_s, Equal);
2521    /// assert_eq!(o_c, Equal);
2522    /// ```
2523    #[inline]
2524    pub fn sin_cos_pi_prec_round(
2525        self,
2526        prec: u64,
2527        rm: RoundingMode,
2528    ) -> (Self, Self, Ordering, Ordering) {
2529        self.sin_cos_with_period_prec_round(2, prec, rm)
2530    }
2531
2532    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2533    /// half-turns, together, rounding both results to the specified precision and with the
2534    /// specified rounding mode. The [`Float`] is taken by reference. Two [`Ordering`]s are also
2535    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
2536    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
2537    /// function returns a `NaN` it also returns `Equal` for it.
2538    ///
2539    /// This is `sin_cos_with_period` with a period of 2: see
2540    /// [`Float::sin_cos_with_period_prec_round_ref`] for the error bounds, the special and
2541    /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
2542    ///
2543    /// # Panics
2544    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2545    /// exactly with the given precision.
2546    ///
2547    /// # Examples
2548    /// ```
2549    /// use malachite_base::rounding_modes::RoundingMode::*;
2550    /// use malachite_float::Float;
2551    /// use std::cmp::Ordering::*;
2552    ///
2553    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_prec_round_ref(10, Floor);
2554    /// assert_eq!(s.to_string(), "0.30859");
2555    /// assert_eq!(c.to_string(), "0.95020");
2556    /// assert_eq!(o_s, Less);
2557    /// assert_eq!(o_c, Less);
2558    /// ```
2559    #[inline]
2560    pub fn sin_cos_pi_prec_round_ref(
2561        &self,
2562        prec: u64,
2563        rm: RoundingMode,
2564    ) -> (Self, Self, Ordering, Ordering) {
2565        self.sin_cos_with_period_prec_round_ref(2, prec, rm)
2566    }
2567
2568    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2569    /// half-turns, together, rounding both results to the nearest value of the specified precision.
2570    /// The [`Float`] is taken by value. Two [`Ordering`]s are also returned, indicating whether the
2571    /// rounded sine and cosine are less than, equal to, or greater than the exact values. Although
2572    /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also
2573    /// returns `Equal` for it.
2574    ///
2575    /// This is `sin_cos_with_period` with a period of 2: see [`Float::sin_cos_with_period_prec`]
2576    /// for the error bounds, the special and closed-form cases, overflow and underflow, and the
2577    /// complexity, with $u = 2$.
2578    ///
2579    /// # Panics
2580    /// Panics if `prec` is zero.
2581    ///
2582    /// # Examples
2583    /// ```
2584    /// use malachite_float::Float;
2585    /// use std::cmp::Ordering::*;
2586    ///
2587    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_prec(10);
2588    /// assert_eq!(s.to_string(), "0.30908");
2589    /// assert_eq!(c.to_string(), "0.95117");
2590    /// assert_eq!(o_s, Greater);
2591    /// assert_eq!(o_c, Greater);
2592    /// ```
2593    #[inline]
2594    pub fn sin_cos_pi_prec(self, prec: u64) -> (Self, Self, Ordering, Ordering) {
2595        self.sin_cos_with_period_prec(2, prec)
2596    }
2597
2598    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2599    /// half-turns, together, rounding both results to the nearest value of the specified precision.
2600    /// The [`Float`] is taken by reference. Two [`Ordering`]s are also returned, indicating whether
2601    /// the rounded sine and cosine are less than, equal to, or greater than the exact values.
2602    /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
2603    /// it also returns `Equal` for it.
2604    ///
2605    /// This is `sin_cos_with_period` with a period of 2: see
2606    /// [`Float::sin_cos_with_period_prec_ref`] for the error bounds, the special and closed-form
2607    /// cases, overflow and underflow, and the complexity, with $u = 2$.
2608    ///
2609    /// # Panics
2610    /// Panics if `prec` is zero.
2611    ///
2612    /// # Examples
2613    /// ```
2614    /// use malachite_float::Float;
2615    /// use std::cmp::Ordering::*;
2616    ///
2617    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_prec_ref(10);
2618    /// assert_eq!(s.to_string(), "0.30908");
2619    /// assert_eq!(c.to_string(), "0.95117");
2620    /// assert_eq!(o_s, Greater);
2621    /// assert_eq!(o_c, Greater);
2622    /// ```
2623    #[inline]
2624    pub fn sin_cos_pi_prec_ref(&self, prec: u64) -> (Self, Self, Ordering, Ordering) {
2625        self.sin_cos_with_period_prec_ref(2, prec)
2626    }
2627
2628    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2629    /// half-turns, together, rounding both results to the precision of the input and with the
2630    /// specified rounding mode. The [`Float`] is taken by value. Two [`Ordering`]s are also
2631    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
2632    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
2633    /// function returns a `NaN` it also returns `Equal` for it.
2634    ///
2635    /// This is `sin_cos_with_period` with a period of 2: see [`Float::sin_cos_with_period_round`]
2636    /// for the error bounds, the special and closed-form cases, overflow and underflow, and the
2637    /// complexity, with $u = 2$.
2638    ///
2639    /// # Panics
2640    /// Panics if `rm` is `Exact` but the results cannot be represented exactly with the precision
2641    /// of the input.
2642    ///
2643    /// # Examples
2644    /// ```
2645    /// use malachite_base::rounding_modes::RoundingMode::*;
2646    /// use malachite_float::Float;
2647    /// use std::cmp::Ordering::*;
2648    ///
2649    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_round(Floor);
2650    /// assert_eq!(s.to_string(), "0.30901699437494734");
2651    /// assert_eq!(c.to_string(), "0.95105651629515342");
2652    /// assert_eq!(o_s, Less);
2653    /// assert_eq!(o_c, Less);
2654    /// ```
2655    #[inline]
2656    pub fn sin_cos_pi_round(self, rm: RoundingMode) -> (Self, Self, Ordering, Ordering) {
2657        self.sin_cos_with_period_round(2, rm)
2658    }
2659
2660    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2661    /// half-turns, together, rounding both results to the precision of the input and with the
2662    /// specified rounding mode. The [`Float`] is taken by reference. Two [`Ordering`]s are also
2663    /// returned, indicating whether the rounded sine and cosine are less than, equal to, or greater
2664    /// than the exact values. Although `NaN`s are not comparable to any [`Float`], whenever this
2665    /// function returns a `NaN` it also returns `Equal` for it.
2666    ///
2667    /// This is `sin_cos_with_period` with a period of 2: see
2668    /// [`Float::sin_cos_with_period_round_ref`] for the error bounds, the special and closed-form
2669    /// cases, overflow and underflow, and the complexity, with $u = 2$.
2670    ///
2671    /// # Panics
2672    /// Panics if `rm` is `Exact` but the results cannot be represented exactly with the precision
2673    /// of the input.
2674    ///
2675    /// # Examples
2676    /// ```
2677    /// use malachite_base::rounding_modes::RoundingMode::*;
2678    /// use malachite_float::Float;
2679    /// use std::cmp::Ordering::*;
2680    ///
2681    /// let (s, c, o_s, o_c) = Float::from(0.1f64).sin_cos_pi_round_ref(Floor);
2682    /// assert_eq!(s.to_string(), "0.30901699437494734");
2683    /// assert_eq!(c.to_string(), "0.95105651629515342");
2684    /// assert_eq!(o_s, Less);
2685    /// assert_eq!(o_c, Less);
2686    /// ```
2687    #[inline]
2688    pub fn sin_cos_pi_round_ref(&self, rm: RoundingMode) -> (Self, Self, Ordering, Ordering) {
2689        self.sin_cos_with_period_round_ref(2, rm)
2690    }
2691
2692    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2693    /// half-turns, together, rounding both results to the precision of the input and to the nearest
2694    /// [`Float`]s. The [`Float`] is taken by value.
2695    ///
2696    /// If either result is equidistant from two [`Float`]s with the precision of the input, the
2697    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2698    /// description of the `Nearest` rounding mode.
2699    ///
2700    /// This is `sin_cos_with_period` with a period of 2: see [`Float::sin_cos_with_period`] for the
2701    /// error bounds, the special and closed-form cases, overflow and underflow, and the complexity,
2702    /// with $u = 2$.
2703    ///
2704    /// If you want to use a rounding mode other than `Nearest`, consider using
2705    /// [`Float::sin_cos_pi_round`] instead. If you want to specify an output precision, consider
2706    /// using [`Float::sin_cos_pi_prec`]. If you want both of these things, consider using
2707    /// [`Float::sin_cos_pi_prec_round`].
2708    ///
2709    /// # Examples
2710    /// ```
2711    /// use malachite_float::Float;
2712    ///
2713    /// let (s, c) = Float::from(0.1f64).sin_cos_pi();
2714    /// assert_eq!(s.to_string(), "0.30901699437494745");
2715    /// assert_eq!(c.to_string(), "0.95105651629515364");
2716    /// ```
2717    #[inline]
2718    pub fn sin_cos_pi(self) -> (Self, Self) {
2719        let prec = self.significant_bits();
2720        let (s, c, _, _) = self.sin_cos_pi_prec(prec);
2721        (s, c)
2722    }
2723
2724    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2725    /// half-turns, together, rounding both results to the precision of the input and to the nearest
2726    /// [`Float`]s. The [`Float`] is taken by reference.
2727    ///
2728    /// If either result is equidistant from two [`Float`]s with the precision of the input, the
2729    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2730    /// description of the `Nearest` rounding mode.
2731    ///
2732    /// This is `sin_cos_with_period` with a period of 2: see [`Float::sin_cos_with_period`] for the
2733    /// error bounds, the special and closed-form cases, overflow and underflow, and the complexity,
2734    /// with $u = 2$.
2735    ///
2736    /// If you want to use a rounding mode other than `Nearest`, consider using
2737    /// [`Float::sin_cos_pi_round_ref`] instead. If you want to specify an output precision,
2738    /// consider using [`Float::sin_cos_pi_prec_ref`]. If you want both of these things, consider
2739    /// using [`Float::sin_cos_pi_prec_round_ref`].
2740    ///
2741    /// # Examples
2742    /// ```
2743    /// use malachite_float::Float;
2744    ///
2745    /// let (s, c) = (&Float::from(0.1f64)).sin_cos_pi_ref();
2746    /// assert_eq!(s.to_string(), "0.30901699437494745");
2747    /// assert_eq!(c.to_string(), "0.95105651629515364");
2748    /// ```
2749    #[inline]
2750    pub fn sin_cos_pi_ref(&self) -> (Self, Self) {
2751        let (s, c, _, _) = self.sin_cos_pi_prec_ref(self.significant_bits());
2752        (s, c)
2753    }
2754
2755    /// Replaces a [`Float`] measured in half-turns with its sine and writes its cosine to `cos`,
2756    /// rounding both results to the specified precision and with the specified rounding mode. The
2757    /// previous value of `cos` is discarded. Two [`Ordering`]s are returned, indicating whether the
2758    /// rounded sine and cosine are less than, equal to, or greater than the exact values. Although
2759    /// `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it also
2760    /// returns `Equal` for it.
2761    ///
2762    /// This is `sin_cos_with_period` with a period of 2: see
2763    /// [`Float::sin_cos_with_period_prec_round_assign`] for the error bounds, the special and
2764    /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
2765    ///
2766    /// # Panics
2767    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2768    /// exactly with the given precision.
2769    ///
2770    /// # Examples
2771    /// ```
2772    /// use malachite_base::num::basic::traits::NaN;
2773    /// use malachite_base::rounding_modes::RoundingMode::*;
2774    /// use malachite_float::Float;
2775    /// use std::cmp::Ordering::*;
2776    ///
2777    /// let mut x = Float::from(0.1f64);
2778    /// let mut c = Float::NAN;
2779    /// assert_eq!(
2780    ///     x.sin_cos_pi_prec_round_assign(&mut c, 10, Floor),
2781    ///     (Less, Less)
2782    /// );
2783    /// assert_eq!(x.to_string(), "0.30859");
2784    /// assert_eq!(c.to_string(), "0.95020");
2785    /// ```
2786    #[inline]
2787    pub fn sin_cos_pi_prec_round_assign(
2788        &mut self,
2789        cos: &mut Self,
2790        prec: u64,
2791        rm: RoundingMode,
2792    ) -> (Ordering, Ordering) {
2793        self.sin_cos_with_period_prec_round_assign(cos, 2, prec, rm)
2794    }
2795
2796    /// Replaces a [`Float`] measured in half-turns with its sine and writes its cosine to `cos`,
2797    /// rounding both results to the nearest value of the specified precision. The previous value of
2798    /// `cos` is discarded. Two [`Ordering`]s are returned, indicating whether the rounded sine and
2799    /// cosine are less than, equal to, or greater than the exact values. Although `NaN`s are not
2800    /// comparable to any [`Float`], whenever this function sets a `NaN` it also returns `Equal` for
2801    /// it.
2802    ///
2803    /// This is `sin_cos_with_period` with a period of 2: see
2804    /// [`Float::sin_cos_with_period_prec_assign`] for the error bounds, the special and closed-form
2805    /// cases, overflow and underflow, and the complexity, with $u = 2$.
2806    ///
2807    /// # Panics
2808    /// Panics if `prec` is zero.
2809    ///
2810    /// # Examples
2811    /// ```
2812    /// use malachite_base::num::basic::traits::NaN;
2813    /// use malachite_float::Float;
2814    /// use std::cmp::Ordering::*;
2815    ///
2816    /// let mut x = Float::from(0.1f64);
2817    /// let mut c = Float::NAN;
2818    /// assert_eq!(x.sin_cos_pi_prec_assign(&mut c, 10), (Greater, Greater));
2819    /// assert_eq!(x.to_string(), "0.30908");
2820    /// assert_eq!(c.to_string(), "0.95117");
2821    /// ```
2822    #[inline]
2823    pub fn sin_cos_pi_prec_assign(&mut self, cos: &mut Self, prec: u64) -> (Ordering, Ordering) {
2824        self.sin_cos_with_period_prec_assign(cos, 2, prec)
2825    }
2826
2827    /// Replaces a [`Float`] measured in half-turns with its sine and writes its cosine to `cos`,
2828    /// rounding both results to the precision of the input and with the specified rounding mode.
2829    /// The previous value of `cos` is discarded. Two [`Ordering`]s are returned, indicating whether
2830    /// the rounded sine and cosine are less than, equal to, or greater than the exact values.
2831    /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it
2832    /// also returns `Equal` for it.
2833    ///
2834    /// This is `sin_cos_with_period` with a period of 2: see
2835    /// [`Float::sin_cos_with_period_round_assign`] for the error bounds, the special and
2836    /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
2837    ///
2838    /// # Panics
2839    /// Panics if `rm` is `Exact` but the results cannot be represented exactly with the precision
2840    /// of the input.
2841    ///
2842    /// # Examples
2843    /// ```
2844    /// use malachite_base::num::basic::traits::NaN;
2845    /// use malachite_base::rounding_modes::RoundingMode::*;
2846    /// use malachite_float::Float;
2847    /// use std::cmp::Ordering::*;
2848    ///
2849    /// let mut x = Float::from(0.1f64);
2850    /// let mut c = Float::NAN;
2851    /// assert_eq!(x.sin_cos_pi_round_assign(&mut c, Floor), (Less, Less));
2852    /// assert_eq!(x.to_string(), "0.30901699437494734");
2853    /// assert_eq!(c.to_string(), "0.95105651629515342");
2854    /// ```
2855    #[inline]
2856    pub fn sin_cos_pi_round_assign(
2857        &mut self,
2858        cos: &mut Self,
2859        rm: RoundingMode,
2860    ) -> (Ordering, Ordering) {
2861        self.sin_cos_with_period_round_assign(cos, 2, rm)
2862    }
2863
2864    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Float`] measured in
2865    /// half-turns, together, rounding both results to the precision of the input and to the nearest
2866    /// [`Float`]s. The [`Float`] is replaced by the sine, and the cosine is written to `cos`, whose
2867    /// previous value is discarded.
2868    ///
2869    /// If either result is equidistant from two [`Float`]s with the precision of the input, the
2870    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2871    /// description of the `Nearest` rounding mode.
2872    ///
2873    /// This is `sin_cos_with_period` with a period of 2: see [`Float::sin_cos_with_period`] for the
2874    /// error bounds, the special and closed-form cases, overflow and underflow, and the complexity,
2875    /// with $u = 2$.
2876    ///
2877    /// If you want to use a rounding mode other than `Nearest`, consider using
2878    /// [`Float::sin_cos_pi_round_assign`] instead. If you want to specify an output precision,
2879    /// consider using [`Float::sin_cos_pi_prec_assign`]. If you want both of these things, consider
2880    /// using [`Float::sin_cos_pi_prec_round_assign`].
2881    ///
2882    /// # Examples
2883    /// ```
2884    /// use malachite_base::num::basic::traits::NaN;
2885    /// use malachite_float::Float;
2886    ///
2887    /// let mut x = Float::from(0.1f64);
2888    /// let mut c = Float::NAN;
2889    /// x.sin_cos_pi_assign(&mut c);
2890    /// assert_eq!(x.to_string(), "0.30901699437494745");
2891    /// assert_eq!(c.to_string(), "0.95105651629515364");
2892    /// ```
2893    #[inline]
2894    pub fn sin_cos_pi_assign(&mut self, cos: &mut Self) {
2895        let prec = self.significant_bits();
2896        self.sin_cos_pi_prec_assign(cos, prec);
2897    }
2898}
2899
2900impl Float {
2901    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Rational`] measured in
2902    /// half-turns, together, rounding both results to the specified precision and with the
2903    /// specified rounding mode, and returning the results as [`Float`]s. The [`Rational`] is taken
2904    /// by value. Two [`Ordering`]s are also returned, indicating whether the rounded sine and
2905    /// cosine are less than, equal to, or greater than the exact values.
2906    ///
2907    /// This is `sin_cos_with_period_rational` with a period of 2: see
2908    /// [`Float::sin_cos_with_period_rational_prec_round`] for the error bounds, the special and
2909    /// closed-form cases (multiples of $1/2$ give exact pairs from $\pm0.0$ and $\pm1$, and odd
2910    /// multiples of $1/6$, $1/4$, and $1/3$ have closed forms for both), overflow and underflow,
2911    /// and the complexity, with $u = 2$.
2912    ///
2913    /// # Panics
2914    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2915    /// exactly with the given precision.
2916    ///
2917    /// # Examples
2918    /// ```
2919    /// use malachite_base::rounding_modes::RoundingMode::*;
2920    /// use malachite_float::Float;
2921    /// use malachite_q::Rational;
2922    /// use std::cmp::Ordering::*;
2923    ///
2924    /// let (s, c, o_s, o_c) =
2925    ///     Float::sin_cos_pi_rational_prec_round(Rational::from_unsigneds(1u8, 7), 10, Floor);
2926    /// assert_eq!(s.to_string(), "0.43359");
2927    /// assert_eq!(c.to_string(), "0.90039");
2928    /// assert_eq!(o_s, Less);
2929    /// assert_eq!(o_c, Less);
2930    ///
2931    /// // a sixth of a half-turn: 1/2 exactly, and sqrt(3)/2
2932    /// let (s, c, o_s, o_c) =
2933    ///     Float::sin_cos_pi_rational_prec_round(Rational::from_unsigneds(1u8, 6), 10, Nearest);
2934    /// assert_eq!(s.to_string(), "0.50000");
2935    /// assert_eq!(c.to_string(), "0.86621");
2936    /// assert_eq!(o_s, Equal);
2937    /// assert_eq!(o_c, Greater);
2938    /// ```
2939    #[inline]
2940    #[allow(clippy::needless_pass_by_value)]
2941    pub fn sin_cos_pi_rational_prec_round(
2942        x: Rational,
2943        prec: u64,
2944        rm: RoundingMode,
2945    ) -> (Self, Self, Ordering, Ordering) {
2946        Self::sin_cos_with_period_rational_prec_round_ref(&x, 2, prec, rm)
2947    }
2948
2949    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Rational`] measured in
2950    /// half-turns, together, rounding both results to the specified precision and with the
2951    /// specified rounding mode, and returning the results as [`Float`]s. The [`Rational`] is taken
2952    /// by reference. Two [`Ordering`]s are also returned, indicating whether the rounded sine and
2953    /// cosine are less than, equal to, or greater than the exact values.
2954    ///
2955    /// This is `sin_cos_with_period_rational` with a period of 2: see
2956    /// [`Float::sin_cos_with_period_rational_prec_round_ref`] for the error bounds, the special and
2957    /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
2958    ///
2959    /// # Panics
2960    /// Panics if `prec` is zero, or if `rm` is `Exact` but the results cannot be represented
2961    /// exactly with the given precision.
2962    ///
2963    /// # Examples
2964    /// ```
2965    /// use malachite_base::rounding_modes::RoundingMode::*;
2966    /// use malachite_float::Float;
2967    /// use malachite_q::Rational;
2968    /// use std::cmp::Ordering::*;
2969    ///
2970    /// let (s, c, o_s, o_c) =
2971    ///     Float::sin_cos_pi_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 7), 10, Floor);
2972    /// assert_eq!(s.to_string(), "0.43359");
2973    /// assert_eq!(c.to_string(), "0.90039");
2974    /// assert_eq!(o_s, Less);
2975    /// assert_eq!(o_c, Less);
2976    /// ```
2977    #[inline]
2978    pub fn sin_cos_pi_rational_prec_round_ref(
2979        x: &Rational,
2980        prec: u64,
2981        rm: RoundingMode,
2982    ) -> (Self, Self, Ordering, Ordering) {
2983        Self::sin_cos_with_period_rational_prec_round_ref(x, 2, prec, rm)
2984    }
2985
2986    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Rational`] measured in
2987    /// half-turns, together, rounding both results to the nearest value of the specified precision,
2988    /// and returning the results as [`Float`]s. The [`Rational`] is taken by value. Two
2989    /// [`Ordering`]s are also returned, indicating whether the rounded sine and cosine are less
2990    /// than, equal to, or greater than the exact values.
2991    ///
2992    /// This is `sin_cos_with_period_rational` with a period of 2: see
2993    /// [`Float::sin_cos_with_period_rational_prec`] for the error bounds, the special and
2994    /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
2995    ///
2996    /// # Panics
2997    /// Panics if `prec` is zero.
2998    ///
2999    /// # Examples
3000    /// ```
3001    /// use malachite_float::Float;
3002    /// use malachite_q::Rational;
3003    /// use std::cmp::Ordering::*;
3004    ///
3005    /// let (s, c, o_s, o_c) =
3006    ///     Float::sin_cos_pi_rational_prec(Rational::from_unsigneds(1u8, 7), 10);
3007    /// assert_eq!(s.to_string(), "0.43408");
3008    /// assert_eq!(c.to_string(), "0.90137");
3009    /// assert_eq!(o_s, Greater);
3010    /// assert_eq!(o_c, Greater);
3011    /// ```
3012    #[inline]
3013    #[allow(clippy::needless_pass_by_value)]
3014    pub fn sin_cos_pi_rational_prec(x: Rational, prec: u64) -> (Self, Self, Ordering, Ordering) {
3015        Self::sin_cos_with_period_rational_prec_ref(&x, 2, prec)
3016    }
3017
3018    /// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Rational`] measured in
3019    /// half-turns, together, rounding both results to the nearest value of the specified precision,
3020    /// and returning the results as [`Float`]s. The [`Rational`] is taken by reference. Two
3021    /// [`Ordering`]s are also returned, indicating whether the rounded sine and cosine are less
3022    /// than, equal to, or greater than the exact values.
3023    ///
3024    /// This is `sin_cos_with_period_rational` with a period of 2: see
3025    /// [`Float::sin_cos_with_period_rational_prec_ref`] for the error bounds, the special and
3026    /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
3027    ///
3028    /// # Panics
3029    /// Panics if `prec` is zero.
3030    ///
3031    /// # Examples
3032    /// ```
3033    /// use malachite_float::Float;
3034    /// use malachite_q::Rational;
3035    /// use std::cmp::Ordering::*;
3036    ///
3037    /// let (s, c, o_s, o_c) =
3038    ///     Float::sin_cos_pi_rational_prec_ref(&Rational::from_unsigneds(1u8, 7), 10);
3039    /// assert_eq!(s.to_string(), "0.43408");
3040    /// assert_eq!(c.to_string(), "0.90137");
3041    /// assert_eq!(o_s, Greater);
3042    /// assert_eq!(o_c, Greater);
3043    /// ```
3044    #[inline]
3045    pub fn sin_cos_pi_rational_prec_ref(
3046        x: &Rational,
3047        prec: u64,
3048    ) -> (Self, Self, Ordering, Ordering) {
3049        Self::sin_cos_with_period_rational_prec_ref(x, 2, prec)
3050    }
3051}
3052
3053impl SinCos for Float {
3054    type Output = Self;
3055
3056    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, taking it by
3057    /// value.
3058    ///
3059    /// If the outputs have a precision, it is the precision of the input. If a result is
3060    /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
3061    /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
3062    /// rounding mode.
3063    ///
3064    /// $$
3065    /// f(x) = (\sin x+\varepsilon_s, \cos x+\varepsilon_c).
3066    /// $$
3067    /// - If $x$ is not finite, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or assumed to be
3068    ///   0.
3069    /// - If $x$ is finite, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin x|\rfloor-p}$ and
3070    ///   $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, where $p$ is the precision of the
3071    ///   input.
3072    ///
3073    /// Special cases:
3074    /// - $f(\text{NaN})=(\text{NaN},\text{NaN})$
3075    /// - $f(\pm\infty)=(\text{NaN},\text{NaN})$
3076    /// - $f(\pm0.0)=(\pm0.0,1.0)$
3077    ///
3078    /// See [`Float::sin_cos_prec_round`] for overflow, underflow, and the complexity.
3079    ///
3080    /// If you want to use a rounding mode other than `Nearest`, consider using
3081    /// [`Float::sin_cos_round`] instead. If you want to specify an output precision, consider using
3082    /// [`Float::sin_cos_prec`] instead. If you want both of these things, consider using
3083    /// [`Float::sin_cos_prec_round`] instead.
3084    ///
3085    /// # Examples
3086    /// ```
3087    /// use malachite_base::num::arithmetic::traits::SinCos;
3088    /// use malachite_base::num::basic::traits::{NaN, NegativeZero, Zero};
3089    /// use malachite_float::Float;
3090    ///
3091    /// let (s, c) = Float::NAN.sin_cos();
3092    /// assert!(s.is_nan());
3093    /// assert!(c.is_nan());
3094    ///
3095    /// let (s, c) = Float::ZERO.sin_cos();
3096    /// assert_eq!(s.to_string(), "0.0");
3097    /// assert_eq!(c.to_string(), "1.0");
3098    ///
3099    /// let (s, c) = Float::NEGATIVE_ZERO.sin_cos();
3100    /// assert_eq!(s.to_string(), "-0.0");
3101    /// assert_eq!(c.to_string(), "1.0");
3102    ///
3103    /// let (s, c) = Float::from_unsigned_prec(1u32, 100).0.sin_cos();
3104    /// assert_eq!(s.to_string(), "0.84147098480789650665250232163005");
3105    /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
3106    /// ```
3107    #[inline]
3108    fn sin_cos(self) -> (Self, Self) {
3109        let prec = self.significant_bits();
3110        let (s, c, _, _) = self.sin_cos_prec_round_ref(prec, Nearest);
3111        (s, c)
3112    }
3113}
3114
3115impl SinCos for &Float {
3116    type Output = Float;
3117
3118    /// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Float`], together, taking it by
3119    /// reference.
3120    ///
3121    /// See [`Float::sin_cos`]; this function behaves the same way.
3122    ///
3123    /// # Examples
3124    /// ```
3125    /// use malachite_base::num::arithmetic::traits::SinCos;
3126    /// use malachite_float::Float;
3127    ///
3128    /// let (s, c) = (&Float::from_unsigned_prec(1u32, 100).0).sin_cos();
3129    /// assert_eq!(s.to_string(), "0.84147098480789650665250232163005");
3130    /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
3131    /// ```
3132    #[inline]
3133    fn sin_cos(self) -> (Float, Float) {
3134        let (s, c, _, _) = self.sin_cos_prec_round_ref(self.significant_bits(), Nearest);
3135        (s, c)
3136    }
3137}
3138
3139impl SinCosAssign for Float {
3140    /// Replaces a [`Float`] with its sine and writes its cosine to `cos`, rounding both results to
3141    /// the nearest value of the input's precision. The previous value of `cos` is discarded.
3142    ///
3143    /// See [`Float::sin_cos`]; this function behaves the same way.
3144    ///
3145    /// # Examples
3146    /// ```
3147    /// use malachite_base::num::arithmetic::traits::SinCosAssign;
3148    /// use malachite_base::num::basic::traits::NaN;
3149    /// use malachite_float::Float;
3150    ///
3151    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
3152    /// let mut c = Float::NAN;
3153    /// x.sin_cos_assign(&mut c);
3154    /// assert_eq!(x.to_string(), "0.84147098480789650665250232163005");
3155    /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
3156    /// ```
3157    #[inline]
3158    fn sin_cos_assign(&mut self, cos: &mut Self) {
3159        let prec = self.significant_bits();
3160        self.sin_cos_prec_round_assign(cos, prec, Nearest);
3161    }
3162}
3163
3164/// Computes $\sin x$ and $\cos x$, the sine and cosine of a primitive float, together. Using this
3165/// function is more accurate than using the default `sin_cos` function or the ones provided by
3166/// `libm`.
3167///
3168/// The results are those of
3169/// [`primitive_float_sin`](crate::float::arithmetic::sin::primitive_float_sin) and
3170/// [`primitive_float_cos`](crate::float::arithmetic::cos::primitive_float_cos), but the argument
3171/// reduction and most of the work are shared, so this is faster than the two calls when both values
3172/// are needed.
3173///
3174/// $$
3175/// f(x) = (\sin x+\varepsilon_s, \cos x+\varepsilon_c).
3176/// $$
3177/// - If $x$ is not finite, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or assumed to be 0.
3178/// - If $x$ is finite, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin x|\rfloor-p}$ and
3179///   $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, where $p$ is the precision of the
3180///   output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
3181///
3182/// Special cases:
3183/// - $f(\text{NaN})=(\text{NaN},\text{NaN})$
3184/// - $f(\pm\infty)=(\text{NaN},\text{NaN})$
3185/// - $f(\pm0.0)=(\pm0.0,1.0)$
3186///
3187/// Overflow is not possible, since the results lie in $[-1, 1]$. The sine is subnormal only when
3188/// $x$ is, and then it is $x$ itself; the cosine is never subnormal. See
3189/// [`primitive_float_sin`](crate::float::arithmetic::sin::primitive_float_sin) and
3190/// [`primitive_float_cos`](crate::float::arithmetic::cos::primitive_float_cos).
3191///
3192/// # Worst-case complexity
3193/// Constant time and additional memory.
3194///
3195/// # Examples
3196/// ```
3197/// use malachite_base::num::float::NiceFloat;
3198/// use malachite_float::float::arithmetic::sin_cos::primitive_float_sin_cos;
3199///
3200/// let (s, c) = primitive_float_sin_cos(f32::NAN);
3201/// assert!(s.is_nan());
3202/// assert!(c.is_nan());
3203///
3204/// let (s, c) = primitive_float_sin_cos(0.0f32);
3205/// assert_eq!(NiceFloat(s), NiceFloat(0.0));
3206/// assert_eq!(NiceFloat(c), NiceFloat(1.0));
3207///
3208/// let (s, c) = primitive_float_sin_cos(1.0f32);
3209/// assert_eq!(NiceFloat(s), NiceFloat(0.84147096));
3210/// assert_eq!(NiceFloat(c), NiceFloat(0.5403023));
3211///
3212/// let (s, c) = primitive_float_sin_cos(1.0f64);
3213/// assert_eq!(NiceFloat(s), NiceFloat(0.8414709848078965));
3214/// assert_eq!(NiceFloat(c), NiceFloat(0.5403023058681398));
3215/// ```
3216#[inline]
3217#[allow(clippy::type_repetition_in_bounds)]
3218pub fn primitive_float_sin_cos<T: PrimitiveFloat>(x: T) -> (T, T)
3219where
3220    Float: From<T> + PartialOrd<T>,
3221    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3222{
3223    emulate_float_to_float_pair_fn(Float::sin_cos_prec, x)
3224}
3225
3226/// Computes $\sin x$ and $\cos x$, the sine and cosine of a [`Rational`], together, returning the
3227/// results as primitive floats.
3228///
3229/// The results are those of
3230/// [`primitive_float_sin_rational`](crate::float::arithmetic::sin::primitive_float_sin_rational)
3231/// and
3232/// [`primitive_float_cos_rational`](crate::float::arithmetic::cos::primitive_float_cos_rational),
3233/// but the rounding of the input, the argument reduction, and most of the work are shared, so this
3234/// is faster than the two calls when both values are needed.
3235///
3236/// $$
3237/// f(x) = (\sin x+\varepsilon_s, \cos x+\varepsilon_c),
3238/// $$
3239/// where $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin x|\rfloor-p}$ and $|\varepsilon_c| <
3240/// 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, and $p$ is the precision of the output (24 if `T` is a
3241/// [`f32`] and 53 if `T` is a [`f64`]).
3242///
3243/// Special cases:
3244/// - $f(0)=(0,1)$
3245///
3246/// Overflow is not possible, since the results lie in $[-1, 1]$. The sine underflows, to a
3247/// subnormal or to zero, when $x$ is tiny, since $\sin x$ is then very close to $x$; the cosine is
3248/// never subnormal. See
3249/// [`primitive_float_sin_rational`](crate::float::arithmetic::sin::primitive_float_sin_rational)
3250/// and
3251/// [`primitive_float_cos_rational`](crate::float::arithmetic::cos::primitive_float_cos_rational).
3252///
3253/// # Worst-case complexity
3254/// $T(m, e) = O((m+e) (\log (m+e))^2 \log\log (m+e))$
3255///
3256/// $M(m, e) = O((m+e) \log (m+e))$
3257///
3258/// where $T$ is time, $M$ is additional memory, $m$ is `x.significant_bits()`, and $e$ is
3259/// `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): for $|x| \geq 2$ the
3260/// argument is reduced modulo $2\pi$, which needs $\pi$ to about $e$ bits.
3261///
3262/// # Examples
3263/// ```
3264/// use malachite_base::num::basic::traits::Zero;
3265/// use malachite_base::num::float::NiceFloat;
3266/// use malachite_float::float::arithmetic::sin_cos::primitive_float_sin_cos_rational;
3267/// use malachite_q::Rational;
3268///
3269/// let (s, c) = primitive_float_sin_cos_rational::<f64>(&Rational::ZERO);
3270/// assert_eq!(NiceFloat(s), NiceFloat(0.0));
3271/// assert_eq!(NiceFloat(c), NiceFloat(1.0));
3272///
3273/// let (s, c) = primitive_float_sin_cos_rational::<f64>(&Rational::from_unsigneds(1u8, 3));
3274/// assert_eq!(NiceFloat(s), NiceFloat(0.32719469679615226));
3275/// assert_eq!(NiceFloat(c), NiceFloat(0.9449569463147377));
3276///
3277/// let (s, c) = primitive_float_sin_cos_rational::<f32>(&Rational::from_unsigneds(1u8, 3));
3278/// assert_eq!(NiceFloat(s), NiceFloat(0.3271947));
3279/// assert_eq!(NiceFloat(c), NiceFloat(0.94495696));
3280/// ```
3281#[inline]
3282#[allow(clippy::type_repetition_in_bounds)]
3283pub fn primitive_float_sin_cos_rational<T: PrimitiveFloat>(x: &Rational) -> (T, T)
3284where
3285    Float: PartialOrd<T>,
3286    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3287{
3288    emulate_rational_to_float_pair_fn(Float::sin_cos_rational_prec_ref, x)
3289}
3290
3291/// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a primitive float
3292/// measured in $u$ths of a turn (so that `u = 360` is degrees), together.
3293///
3294/// The results are those of
3295/// [`primitive_float_sin_with_period`](super::sin::primitive_float_sin_with_period) and
3296/// [`primitive_float_cos_with_period`](super::cos::primitive_float_cos_with_period), but the
3297/// argument reduction and most of the work are shared, so this is faster than the two calls when
3298/// both values are needed.
3299///
3300/// $$
3301/// f(x,u) = (\sin(2\pi x/u)+\varepsilon_s, \cos(2\pi x/u)+\varepsilon_c).
3302/// $$
3303/// - If $x$ is not finite or $u=0$, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or assumed
3304///   to be 0.
3305/// - If $x$ is finite and $u\neq 0$, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin(2\pi
3306///   x/u)|\rfloor-p}$ and $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$, where
3307///   $p$ is the precision of the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
3308///
3309/// Special cases:
3310/// - $f(\text{NaN},u)=(\text{NaN},\text{NaN})$
3311/// - $f(\pm\infty,u)=(\text{NaN},\text{NaN})$
3312/// - $f(x,0)=(\text{NaN},\text{NaN})$
3313/// - $f(\pm0.0,u)=(\pm0.0,1.0)$
3314/// - If $x/u$ is a multiple of $1/4$, both results are exact: the sine is $0.0$ with the sign of
3315///   $x$, $1$, or $-1$, and the cosine is $1$, $0.0$, or $-1$.
3316///
3317/// Overflow is not possible, since the results lie in $[-1, 1]$. The sine underflows, to a
3318/// subnormal or to zero, only when $2\pi x/u$ does, which takes a subnormal $x$ or a large $u$; the
3319/// cosine is never subnormal. See
3320/// [`primitive_float_sin_with_period`](super::sin::primitive_float_sin_with_period) and
3321/// [`primitive_float_cos_with_period`](super::cos::primitive_float_cos_with_period).
3322///
3323/// # Worst-case complexity
3324/// Constant time and additional memory.
3325///
3326/// # Examples
3327/// ```
3328/// use malachite_base::num::float::NiceFloat;
3329/// use malachite_float::float::arithmetic::sin_cos::primitive_float_sin_cos_with_period;
3330///
3331/// let (s, c) = primitive_float_sin_cos_with_period(f32::NAN, 360);
3332/// assert!(s.is_nan());
3333/// assert!(c.is_nan());
3334///
3335/// let (s, c) = primitive_float_sin_cos_with_period(1.0f32, 0);
3336/// assert!(s.is_nan());
3337/// assert!(c.is_nan());
3338///
3339/// let (s, c) = primitive_float_sin_cos_with_period(90.0f32, 360);
3340/// assert_eq!(NiceFloat(s), NiceFloat(1.0));
3341/// assert_eq!(NiceFloat(c), NiceFloat(0.0));
3342///
3343/// let (s, c) = primitive_float_sin_cos_with_period(30.0f64, 360);
3344/// assert_eq!(NiceFloat(s), NiceFloat(0.5));
3345/// assert_eq!(NiceFloat(c), NiceFloat(0.8660254037844386));
3346///
3347/// let (s, c) = primitive_float_sin_cos_with_period(1.0f32, 7);
3348/// assert_eq!(NiceFloat(s), NiceFloat(0.7818315));
3349/// assert_eq!(NiceFloat(c), NiceFloat(0.6234898));
3350///
3351/// let (s, c) = primitive_float_sin_cos_with_period(1.0f64, 7);
3352/// assert_eq!(NiceFloat(s), NiceFloat(0.7818314824680298));
3353/// assert_eq!(NiceFloat(c), NiceFloat(0.6234898018587335));
3354/// ```
3355#[inline]
3356#[allow(clippy::type_repetition_in_bounds)]
3357pub fn primitive_float_sin_cos_with_period<T: PrimitiveFloat>(x: T, u: u64) -> (T, T)
3358where
3359    Float: From<T> + PartialOrd<T>,
3360    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3361{
3362    emulate_float_to_float_pair_fn(|x, prec| Float::sin_cos_with_period_prec(x, u, prec), x)
3363}
3364
3365/// Computes $\sin(2\pi x/u)$ and $\cos(2\pi x/u)$, the sine and cosine of a [`Rational`] measured
3366/// in $u$ths of a turn (so that `u = 360` is degrees), together, returning the results as primitive
3367/// floats.
3368///
3369/// The results are those of
3370/// [`primitive_float_sin_with_period_rational`](super::sin::primitive_float_sin_with_period_rational)
3371/// and
3372/// [`primitive_float_cos_with_period_rational`](super::cos::primitive_float_cos_with_period_rational),
3373/// but the reduction of the fraction of a turn and most of the work are shared, so this is faster
3374/// than the two calls when both values are needed.
3375///
3376/// $$
3377/// f(x,u) = (\sin(2\pi x/u)+\varepsilon_s, \cos(2\pi x/u)+\varepsilon_c).
3378/// $$
3379/// - If $u=0$, $\varepsilon_s$ and $\varepsilon_c$ may be ignored or assumed to be 0.
3380/// - If $u\neq 0$, then $|\varepsilon_s| < 2^{\lfloor\log_2 |\sin(2\pi x/u)|\rfloor-p}$ and
3381///   $|\varepsilon_c| < 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$, where $p$ is the precision of
3382///   the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
3383///
3384/// Special cases:
3385/// - $f(x,0)=(\text{NaN},\text{NaN})$
3386/// - $f(0,u)=(0,1)$
3387/// - If $x/u$ is a multiple of $1/4$, both results are exact: the sine is $0.0$ with the sign of
3388///   $x$, $1$, or $-1$, and the cosine is $1$, $0.0$, or $-1$.
3389///
3390/// Overflow is not possible, since the results lie in $[-1, 1]$. The sine underflows, to a
3391/// subnormal or to zero, only when $2\pi x/u$ does, for a tiny $x/u$; the cosine is never
3392/// subnormal. See
3393/// [`primitive_float_sin_with_period_rational`](super::sin::primitive_float_sin_with_period_rational)
3394/// and
3395/// [`primitive_float_cos_with_period_rational`](super::cos::primitive_float_cos_with_period_rational).
3396///
3397/// # Worst-case complexity
3398/// $T(m) = O(m (\log m)^2 \log\log m)$
3399///
3400/// $M(m) = O(m \log m)$
3401///
3402/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`: the fraction of
3403/// a turn is reduced modulo 1 exactly, so the magnitude of $x$ does not drive the cost.
3404///
3405/// # Examples
3406/// ```
3407/// use malachite_base::num::basic::traits::Zero;
3408/// use malachite_base::num::float::NiceFloat;
3409/// use malachite_float::float::arithmetic::sin_cos::primitive_float_sin_cos_with_period_rational;
3410/// use malachite_q::Rational;
3411///
3412/// let (s, c) = primitive_float_sin_cos_with_period_rational::<f64>(&Rational::ZERO, 0);
3413/// assert!(s.is_nan());
3414/// assert!(c.is_nan());
3415///
3416/// let (s, c) = primitive_float_sin_cos_with_period_rational::<f64>(&Rational::ZERO, 360);
3417/// assert_eq!(NiceFloat(s), NiceFloat(0.0));
3418/// assert_eq!(NiceFloat(c), NiceFloat(1.0));
3419///
3420/// // a twelfth of a turn: exactly 1/2, and sqrt(3)/2
3421/// let (s, c) =
3422///     primitive_float_sin_cos_with_period_rational::<f64>(&Rational::from_unsigneds(1u8, 12), 1);
3423/// assert_eq!(NiceFloat(s), NiceFloat(0.5));
3424/// assert_eq!(NiceFloat(c), NiceFloat(0.8660254037844386));
3425///
3426/// let (s, c) =
3427///     primitive_float_sin_cos_with_period_rational::<f32>(&Rational::from_unsigneds(1u8, 7), 1);
3428/// assert_eq!(NiceFloat(s), NiceFloat(0.7818315));
3429/// assert_eq!(NiceFloat(c), NiceFloat(0.6234898));
3430/// ```
3431#[inline]
3432#[allow(clippy::type_repetition_in_bounds)]
3433#[cfg_attr(dylint_lib = "malachite_lints", expect(long_lines))]
3434pub fn primitive_float_sin_cos_with_period_rational<T: PrimitiveFloat>(
3435    x: &Rational,
3436    u: u64,
3437) -> (T, T)
3438where
3439    Float: PartialOrd<T>,
3440    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3441{
3442    emulate_rational_to_float_pair_fn(
3443        |x, prec| Float::sin_cos_with_period_rational_prec_ref(x, u, prec),
3444        x,
3445    )
3446}
3447
3448/// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a primitive float measured in
3449/// half-turns, together.
3450///
3451/// This is `primitive_float_sin_cos_with_period` with a period of 2: see
3452/// [`primitive_float_sin_cos_with_period`] for the error bounds and the special cases, with $u =
3453/// 2$. Multiples of $1/2$ give exact pairs from $\pm0.0$ (with the sign of the input for the sine)
3454/// and $\pm1$.
3455///
3456/// # Worst-case complexity
3457/// Constant time and additional memory.
3458///
3459/// # Examples
3460/// ```
3461/// use malachite_base::num::float::NiceFloat;
3462/// use malachite_float::float::arithmetic::sin_cos::primitive_float_sin_cos_pi;
3463///
3464/// let (s, c) = primitive_float_sin_cos_pi(f32::NAN);
3465/// assert!(s.is_nan());
3466/// assert!(c.is_nan());
3467///
3468/// let (s, c) = primitive_float_sin_cos_pi(0.5f32);
3469/// assert_eq!(NiceFloat(s), NiceFloat(1.0));
3470/// assert_eq!(NiceFloat(c), NiceFloat(0.0));
3471///
3472/// let (s, c) = primitive_float_sin_cos_pi(1.0f64);
3473/// assert_eq!(NiceFloat(s), NiceFloat(0.0));
3474/// assert_eq!(NiceFloat(c), NiceFloat(-1.0));
3475///
3476/// let (s, c) = primitive_float_sin_cos_pi(0.1f32);
3477/// assert_eq!(NiceFloat(s), NiceFloat(0.309017));
3478/// assert_eq!(NiceFloat(c), NiceFloat(0.95105654));
3479///
3480/// let (s, c) = primitive_float_sin_cos_pi(0.1f64);
3481/// assert_eq!(NiceFloat(s), NiceFloat(0.30901699437494745));
3482/// assert_eq!(NiceFloat(c), NiceFloat(0.9510565162951535));
3483/// ```
3484#[inline]
3485#[allow(clippy::type_repetition_in_bounds)]
3486pub fn primitive_float_sin_cos_pi<T: PrimitiveFloat>(x: T) -> (T, T)
3487where
3488    Float: From<T> + PartialOrd<T>,
3489    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3490{
3491    primitive_float_sin_cos_with_period(x, 2)
3492}
3493
3494/// Computes $\sin(\pi x)$ and $\cos(\pi x)$, the sine and cosine of a [`Rational`] measured in
3495/// half-turns, together, returning the results as primitive floats.
3496///
3497/// This is `primitive_float_sin_cos_with_period_rational` with a period of 2: see
3498/// [`primitive_float_sin_cos_with_period_rational`] for the error bounds, the special cases, and
3499/// the complexity, with $u = 2$.
3500///
3501/// # Worst-case complexity
3502/// $T(m) = O(m (\log m)^2 \log\log m)$
3503///
3504/// $M(m) = O(m \log m)$
3505///
3506/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`.
3507///
3508/// # Examples
3509/// ```
3510/// use malachite_base::num::float::NiceFloat;
3511/// use malachite_float::float::arithmetic::sin_cos::primitive_float_sin_cos_pi_rational;
3512/// use malachite_q::Rational;
3513///
3514/// // a sixth of a half-turn: exactly 1/2, and sqrt(3)/2
3515/// let (s, c) = primitive_float_sin_cos_pi_rational::<f64>(&Rational::from_unsigneds(1u8, 6));
3516/// assert_eq!(NiceFloat(s), NiceFloat(0.5));
3517/// assert_eq!(NiceFloat(c), NiceFloat(0.8660254037844386));
3518///
3519/// let (s, c) = primitive_float_sin_cos_pi_rational::<f64>(&Rational::from_unsigneds(1u8, 7));
3520/// assert_eq!(NiceFloat(s), NiceFloat(0.4338837391175581));
3521/// assert_eq!(NiceFloat(c), NiceFloat(0.9009688679024191));
3522/// ```
3523#[inline]
3524#[allow(clippy::type_repetition_in_bounds)]
3525pub fn primitive_float_sin_cos_pi_rational<T: PrimitiveFloat>(x: &Rational) -> (T, T)
3526where
3527    Float: PartialOrd<T>,
3528    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3529{
3530    primitive_float_sin_cos_with_period_rational(x, 2)
3531}