malachite_float/float/arithmetic/cos.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5// Copyright © 2001-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 cosine. `mpfr_cos` (`cos.c`) reduces an argument with |x| >= 4 modulo 2 pi using
16// `mpfr_remainder`, halves the (squared) reduced argument K times, sums the Taylor series of cos in
17// integer arithmetic (`mpfr_cos2_aux`), and undoes the halvings with cos(2x) = 2cos^2(x) - 1, all
18// inside a Ziv loop. For precisions at or above `SINCOS_THRESHOLD`, the binary-splitting tier
19// `sin_cos_fast` in sin_cos.rs (MPFR's `mpfr_cos_fast`, built on `mpfr_sincos_fast`) is used
20// instead.
21
22use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
23use crate::float::arithmetic::exp::{get_z_2exp, one_neighbor};
24use crate::float::arithmetic::round_near_x::float_round_near_x;
25use crate::float::arithmetic::sin_cos::{SINCOS_THRESHOLD, sin_cos_fast};
26use crate::{ComparableFloatRef, Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
27use core::cmp::Ordering::{self, Equal, Greater, Less};
28use core::cmp::{max, min};
29use malachite_base::fail_on_untested_path;
30use malachite_base::num::arithmetic::traits::{
31 Abs, CeilingLogBase2, Cos, CosAssign, DivRoundAssign, FloorLogBase2, FloorSqrt, Mod,
32 ModPowerOf2, NegAssign, Parity, PowerOf2, Square, SubMul, UnsignedAbs,
33};
34use malachite_base::num::basic::floats::PrimitiveFloat;
35use malachite_base::num::basic::integers::PrimitiveInt;
36use malachite_base::num::basic::traits::{NaN as NaNTrait, One, Zero as ZeroTrait};
37use malachite_base::num::comparison::traits::PartialOrdAbs;
38use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
39use malachite_base::num::logic::traits::SignificantBits;
40use malachite_base::rounding_modes::RoundingMode::{self, *};
41use malachite_nz::integer::Integer;
42use malachite_nz::natural::Natural;
43use malachite_nz::natural::arithmetic::float::round::float_can_round;
44use malachite_nz::platform::Limb;
45use malachite_q::Rational;
46
47// f <- 1 - r/2! + r^2/4! + ... + (-1)^l r^l/(2l)! + ...
48//
49// Assumes |r| < 1/2, and f, r have the same precision. Returns e such that the error on f is
50// bounded by 2^e ulps.
51//
52// The smallest i such that i*(i+1) might not fit in a u64. Reaching it would take 2^32 terms, so
53// the two-step division below is never exercised in practice.
54const MAXI: u64 = 1 << (u64::WIDTH >> 1);
55
56// This is mpfr_cos2_aux from cos.c, MPFR 4.2.2.
57fn cos2_aux(r: &Float, p: u64) -> (Float, u64) {
58 let exp_r = i64::from(r.get_exponent().unwrap());
59 assert!(exp_r <= -1);
60 let (mut x, mut ex) = get_z_2exp(r.clone()); // r = x*2^ex
61 // Remove trailing zeroes. Since x comes from a regular MPFR number, due to the constraints on
62 // the exponent and the precision, there can be no integer overflow below.
63 let l = x.trailing_zeros().unwrap();
64 ex += i64::exact_from(l);
65 x >>= l;
66 // since |r| < 1, r = x*2^ex, and x is an integer, necessarily ex < 0 bound for number of
67 // iterations
68 let mut imax = p / u64::exact_from(-exp_r);
69 imax += u64::from(imax == 0);
70 let q = (imax.ceiling_log_base_2() << 1) + 4; // bound for (3l)^2
71 let mut s = Integer::power_of_2(p + q); // initialize sum with 1, scaled by 2^(p+q)
72 let mut t = s.clone(); // invariant: t is previous term
73 let mut i: u64 = 1;
74 loop {
75 let m = t.significant_bits();
76 if m < q {
77 break;
78 }
79 // adjust precision of x to that of t
80 let mut l = x.significant_bits();
81 if l > m {
82 l -= m;
83 x >>= l;
84 ex += i64::exact_from(l);
85 }
86 // multiply t by r
87 t *= &x;
88 t >>= u64::exact_from(-ex);
89 // divide t by i*(i+1)
90 if i < MAXI {
91 t.div_round_assign(Integer::from(i * (i + 1)), Floor);
92 } else {
93 t.div_round_assign(Integer::from(i), Floor);
94 t.div_round_assign(Integer::from(i + 1), Floor);
95 }
96 // if m is the (current) number of bits of t, we can consider that all operations on t so
97 // far had precision >= m, so we can prove by induction that the relative error on t is of
98 // the form (1+u)^(3l)-1, where |u| <= 2^(-m), and l=(i+1)/2 is the # of loops. Since
99 // |(1+x^2)^(1/x) - 1| <= 4x/3 for |x| <= 1/2, for |u| <= 1/(3l)^2, the absolute error is
100 // bounded by 4/3*(3l)*2^(-m)*t <= 4*l since |t| < 2^m. Therefore the error on s is bounded
101 // by 2*l*(l+1).
102 //
103 // add or subtract to s
104 if i % 4 == 1 {
105 s -= &t;
106 } else {
107 s += &t;
108 }
109 i += 2;
110 }
111 let f = Float::from_integer_prec(s, p).0 >> (p + q);
112 let l = (i - 1) >> 1; // number of iterations
113 (f, ((l + 1).ceiling_log_base_2() << 1) + 1) // bound is 2l(l+1)
114}
115
116// Returns a partial sum S_k = t - t^3/3! + ... of the sine series for a `Rational` t with |t| < 1,
117// which is an upper bound on sin(t) if `upper` is true and a lower bound otherwise, and is within
118// |t| 2^-(w + 2) of sin(t). The bound thus tightens with the working precision w, unlike a fixed
119// bound such as t - t^3/6 <= sin(t) <= t, which for |t| near 2^-64 leaves a relative gap of about
120// 2^-128 that no amount of pi precision can close.
121//
122// The series alternates with decreasing terms, so |sin(t) - S_k| <= |t|^(2k + 1) / (2k + 1)!, and
123// S_k is above sin(t) exactly when the omitted term t^(2k + 1) / (2k + 1)! is negative, i.e. when k
124// is odd and t > 0, or k is even and t < 0. The number of terms is chosen from the bit length of t
125// alone, so when the first term suffices (as in underflow cases, where |t| is tiny) t itself, or t
126// shifted by the error margin, is the bound, and no product is formed.
127pub(crate) fn sin_bound(t: &Rational, w: u64, upper: bool) -> Rational {
128 if *t == 0u32 {
129 return Rational::ZERO;
130 }
131 // |t| < 2^(log + 1), with log < 0
132 let log = t.floor_log_base_2_abs();
133 assert!(log < 0);
134 // |t|^(2k) / (2k + 1)! < 2^(2k (log + 1) - log_factorial), where log_factorial <= log2((2k +
135 // 1)!)
136 let mut k = 1u64;
137 let mut log_factorial = 2u64; // floor(log2(2)) + floor(log2(3))
138 let target = -i128::from(w) - 4;
139 while i128::from(k << 1) * i128::from(log + 1) - i128::from(log_factorial) > target {
140 k += 1;
141 let two_k = k << 1;
142 log_factorial += two_k.floor_log_base_2() + (two_k + 1).floor_log_base_2();
143 }
144 let mut s = t.clone();
145 if k > 1 {
146 let t_squared = t.square();
147 let mut term = t.clone();
148 for j in 1..k {
149 term *= &t_squared;
150 term /= Rational::from((j << 1) * ((j << 1) + 1));
151 term.neg_assign();
152 s += &term;
153 }
154 }
155 // S_k is within |t| 2^-(w + 4) of sin(t). If it bounds sin(t) on the wrong side, moving it by
156 // |S_k| 2^-(w + 3) >= |t| 2^-(w + 4) (since |S_k| >= |t| / 2) gives a bound on the right side,
157 // within |t| 2^-(w + 2). The move is done as a multiplication by 2^(w + 3) ± 1 followed by a
158 // shift, which only reduces a small integer against the denominator; adding a shifted copy
159 // would instead take a GCD of two denominators, ruinous when t has a 2^30-bit one. (Taking one
160 // more series term would be worse still, squaring t.)
161 if upper != ((*t > 0u32) == k.odd()) {
162 let shift = w + 3;
163 let mut factor = Natural::power_of_2(shift);
164 if upper == (s > 0u32) {
165 factor += Natural::ONE;
166 } else {
167 factor -= Natural::ONE;
168 }
169 s *= Rational::from(factor);
170 s >>= shift;
171 }
172 s
173}
174
175// Rounds both ends of an open bracket (lo, hi) known to contain a transcendental value; if the two
176// ends round to the same `Float` on the same side of it, that settles the result. The value is
177// strictly inside the bracket, so an end that is exactly representable is not itself a candidate:
178// values just inside round either to that end (with the `Ordering` of that side) or, when the mode
179// rounds them away from it, to its neighbor. (A partial sum of a series can be exactly the input,
180// as t is for sin(t); merging the end's own `Equal` with the other side's `Ordering` would then
181// never let a directed rounding resolve, however narrow the bracket.) The comparison is
182// sign-sensitive, so a bracket straddling or touching zero is never accepted.
183pub(crate) fn round_bracket(
184 lo: &Rational,
185 hi: &Rational,
186 prec: u64,
187 rm: RoundingMode,
188) -> Option<(Float, Ordering)> {
189 let (mut f_lo, mut o_lo) = Float::from_rational_prec_round_ref(lo, prec, rm);
190 let (mut f_hi, mut o_hi) = Float::from_rational_prec_round_ref(hi, prec, rm);
191 if o_lo == Equal {
192 if f_lo == 0u32 {
193 return None;
194 }
195 // values just above lo
196 let up = match rm {
197 Ceiling => true,
198 Up => f_lo > 0u32,
199 Down => f_lo < 0u32,
200 _ => false,
201 };
202 o_lo = if up {
203 f_lo.increment();
204 Greater
205 } else {
206 Less
207 };
208 }
209 if o_hi == Equal {
210 if f_hi == 0u32 {
211 return None;
212 }
213 // values just below hi
214 let down = match rm {
215 Floor => true,
216 Down => f_hi > 0u32,
217 Up => f_hi < 0u32,
218 _ => false,
219 };
220 o_hi = if down {
221 f_hi.decrement();
222 Less
223 } else {
224 Greater
225 };
226 }
227 (o_lo == o_hi && ComparableFloatRef(&f_lo) == ComparableFloatRef(&f_hi)).then_some((f_lo, o_lo))
228}
229
230// `round_bracket` for the open bracket (2^k lo, 2^k hi) of nonzero Floats of the same sign, scaled
231// by a power of 2 so large that its ends would not fit in `Rational`s of reasonable size: each end
232// is shifted with the rounding mode, which performs any underflow or overflow rounding. As in
233// `round_bracket`, an end that is exactly representable after the shift is not itself a candidate,
234// since the value is strictly inside the bracket.
235pub(crate) fn round_scaled_bracket(
236 lo: &Float,
237 hi: &Float,
238 k: i64,
239 prec: u64,
240 rm: RoundingMode,
241) -> Option<(Float, Ordering)> {
242 let (mut f_lo, mut o_lo) = lo.shl_prec_round_ref(k, prec, rm);
243 let (mut f_hi, mut o_hi) = hi.shl_prec_round_ref(k, prec, rm);
244 if o_lo == Equal {
245 // an end with all-zero bits below the output precision values just above lo
246 let up = match rm {
247 Ceiling => true,
248 Up => f_lo > 0u32,
249 Down => f_lo < 0u32,
250 _ => false,
251 };
252 o_lo = if up {
253 f_lo.increment();
254 Greater
255 } else {
256 Less
257 };
258 }
259 if o_hi == Equal {
260 // an end with all-zero bits below the output precision; not reached by any test
261 fail_on_untested_path("round_scaled_bracket, exact upper end");
262 // values just below hi
263 let down = match rm {
264 Floor => true,
265 Down => f_hi > 0u32,
266 Up => f_hi < 0u32,
267 _ => false,
268 };
269 o_hi = if down {
270 f_hi.decrement();
271 Less
272 } else {
273 Greater
274 };
275 }
276 (o_lo == o_hi && ComparableFloatRef(&f_lo) == ComparableFloatRef(&f_hi)).then_some((f_lo, o_lo))
277}
278
279// cos(x) for a nonzero x so small that 1 - x^2/2 <= cos(x) < 1 lies within half an ulp of 1 at
280// precision `prec`: the result is 1, or its predecessor for rounding toward zero.
281pub(crate) fn cos_rational_tiny(prec: u64, rm: RoundingMode) -> (Float, Ordering) {
282 match rm {
283 Floor | Down => (one_neighbor(prec, false), Less),
284 _ => (Float::one_prec(prec), Greater),
285 }
286}
287
288// Sums the cosine series 1 - x^2/2! + x^4/4! - ... in `Rational` arithmetic for a nonzero |x| < 1
289// too small to be a `Float`. The terms alternate in sign with decreasing magnitude, so cos(x) lies
290// between consecutive partial sums, and the bracket is tightened until both ends round the same
291// way. Only reachable for a precision beyond 2^31 bits: any smaller precision takes the tiny path.
292fn cos_rational_series(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
293 fail_on_untested_path("cos_rational_series");
294 let x_squared = x.square();
295 let mut s = Rational::ONE;
296 let mut term = Rational::ONE;
297 let mut k = 1u64;
298 loop {
299 term *= &x_squared;
300 term /= Rational::from((k << 1) * ((k << 1) - 1));
301 term.neg_assign();
302 let s_next = &s + &term;
303 let (lo, hi) = if s < s_next {
304 (&s, &s_next)
305 } else {
306 (&s_next, &s)
307 };
308 if let Some(result) = round_bracket(lo, hi, prec, rm) {
309 return result;
310 }
311 s = s_next;
312 k += 1;
313 }
314}
315
316// Reduces a `Rational` too large to be a `Float` modulo 2 pi, using pi to exp_x + w bits, so that
317// the reduced value y satisfies |x - 2 pi k - y| <= 2^(2 - w): |k| < 2^exp_x, and 2 pi is known to
318// within 2^(2 - exp_x - w).
319pub(crate) fn reduce_huge(x: &Rational, exp_x: i64, w: u64) -> Rational {
320 let two_pi = Rational::exact_from(&(Float::pi_prec(u64::exact_from(exp_x) + w).0 << 1u32));
321 let k = Integer::rounding_from(x / &two_pi, Nearest).0;
322 x.sub_mul(&two_pi, &Rational::from(k))
323}
324
325// cos(y) (if `cos` is true) or sin(y) for a `Rational` y within about 2^-cancel of a zero of the
326// function, an odd multiple of pi/2 for cos or a multiple of pi for sin (cancel >= 64 and cancel >=
327// prec / 16), where the general bracket would need its working precision raised by `cancel` bits to
328// resolve the result. As in `trig_near_zero`, write y = n pi/2 + delta with n odd, so that cos(y) =
329// -sin(delta) if n = 1 mod 4 and sin(delta) if n = 3 mod 4, or y = n pi + delta, so that sin(y) =
330// (-1)^n sin(delta); here delta is a `Rational` known up to the error in pi, and sin(delta) is
331// bracketed by partial sums of its series. `extra`, if present, is the exponent of an additional
332// error in y itself (from a reduction modulo 2 pi), and `w` is the working precision the caller
333// reached, which is raised until the bracket rounds unambiguously. The bracket of
334// `trig_rational_near_zero`, computed with the working precision raised, as there, until the
335// bracket is narrower than 2^-(target + 4) relative to the value: for a consumer that combines the
336// tiny value with others before rounding (the tangent).
337pub(crate) fn trig_rational_near_zero_bracket(
338 y: &Rational,
339 exp_y: i64,
340 extra: Option<i64>,
341 mut w: u64,
342 target: u64,
343 cos: bool,
344) -> (Rational, Rational) {
345 let mut increment = Limb::WIDTH;
346 let w_hint = y.denominator_ref().significant_bits() + target + 64;
347 loop {
348 let (lo, hi) = trig_rational_near_zero_step(y, exp_y, extra, w, cos);
349 if (&hi - &lo) << (target + 4) <= (&lo).abs() {
350 return (lo, hi);
351 }
352 w = max(w + increment, min(w_hint, w << 3));
353 increment = w >> 1;
354 }
355}
356
357// One bracket of `trig_rational_near_zero` at working precision w.
358fn trig_rational_near_zero_step(
359 y: &Rational,
360 exp_y: i64,
361 extra: Option<i64>,
362 w: u64,
363 cos: bool,
364) -> (Rational, Rational) {
365 let pi = Rational::exact_from(&Float::pi_prec(u64::exact_from(max(exp_y, 1)) + w).0);
366 let (n, negate, multiple) = if cos {
367 let n = Integer::rounding_from((y / &pi) << 1u32, Nearest).0;
368 assert!(n.odd());
369 let negate = (&n).mod_power_of_2(2) == 1u32;
370 (n, negate, pi >> 1u32)
371 } else {
372 let n = Integer::rounding_from(y / &pi, Nearest).0;
373 let negate = n.odd();
374 (n, negate, pi)
375 };
376 let delta = y.sub_mul(&multiple, &Rational::from(&n));
377 let mut e = Rational::power_of_2(1 - i64::exact_from(w));
378 if let Some(extra) = extra {
379 e += Rational::power_of_2(extra);
380 }
381 let d_lo = &delta - &e;
382 let d_hi = delta + e;
383 // |delta| is tiny, so sin is increasing on [d_lo, d_hi] and sin(delta) lies between sin(d_lo)
384 // and sin(d_hi)
385 let sin_lo = sin_bound(&d_lo, w, false);
386 let sin_hi = sin_bound(&d_hi, w, true);
387 if negate {
388 (-sin_hi, -sin_lo)
389 } else {
390 (sin_lo, sin_hi)
391 }
392}
393
394pub(crate) fn trig_rational_near_zero(
395 y: &Rational,
396 exp_y: i64,
397 prec: u64,
398 rm: RoundingMode,
399 extra: Option<i64>,
400 mut w: u64,
401 cos: bool,
402) -> (Float, Ordering) {
403 let mut increment = Limb::WIDTH;
404 // A rational y = a/b is typically no closer to n pi/2 than about 1/b (a dyadic approximation of
405 // pi/2 to k bits, for instance, is off by about 2^-k), so a precision that resolves delta at
406 // that scale is a good first target: as in `cos_near_zero`, w at least grows by half each time
407 // and by up to 8 times to reach the hint, so that the early iterations cost a small fraction of
408 // the last one.
409 let w_hint = y.denominator_ref().significant_bits() + prec + 64;
410 loop {
411 let (lo, hi) = trig_rational_near_zero_step(y, exp_y, extra, w, cos);
412 if let Some(result) = round_bracket(&lo, &hi, prec, rm) {
413 return result;
414 }
415 w = max(w + increment, min(w_hint, w << 3));
416 increment = w >> 1;
417 }
418}
419
420// Computes cos(x) for a nonzero `Rational` x, rounded to precision `prec` with rounding mode `rm`.
421// (cos(0) = 1 is handled by the caller.) The cosine of a nonzero rational is transcendental, so the
422// result is never exactly representable and `rm` must not be `Exact`.
423//
424// The general case rounds x to a `Float` y_f at a working precision w, takes its correctly rounded
425// cosine c_f, and brackets cos(x) using |cos(x) - cos(y_f)| <= |x - y_f|, the rounding error of
426// c_f, and, for an x too large to be a `Float`, the error of a `Rational` reduction modulo 2 pi.
427// The bracket is rounded in `Rational` arithmetic, and w is raised until both ends agree. Unlike
428// `exp_rational_helper`'s bracket of x itself, this needs no monotonicity.
429pub(crate) fn cos_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
430 assert_ne!(rm, Exact, "Inexact cos");
431 let exp_x = x.floor_log_base_2_abs() + 1; // the MPFR-style exponent of x
432 // 1 - cos(x) <= x^2/2 < 2^(2 exp_x - 1): when that is at most 2^(-prec - 1), cos(x) rounds to 1
433 if 1 - (exp_x << 1) > i64::exact_from(prec) {
434 return cos_rational_tiny(prec, rm);
435 }
436 // x is too small to be a `Float` but `prec` is so large that cos(x) does not round to 1
437 if exp_x <= Float::MIN_EXPONENT_I64 {
438 return cos_rational_series(x, prec, rm);
439 }
440 let huge = exp_x >= Float::MAX_EXPONENT_I64;
441 let mut w = prec + 10;
442 let mut increment = Limb::WIDTH;
443 loop {
444 let reduced;
445 let (y, extra) = if huge {
446 reduced = reduce_huge(x, exp_x, w);
447 (&reduced, Some(2 - i64::exact_from(w)))
448 } else {
449 (x, None)
450 };
451 let (y_f, y_o) = Float::from_rational_prec_ref(y, w);
452 if !huge && y_o == Equal {
453 // x is exactly representable at w bits, so cos(x) is simply its cosine
454 return cos_prec_round_normal_ref(&y_f, prec, rm);
455 }
456 let c_f = (&y_f).cos();
457 // The exponents of y and c_f, as `Float`s would have them (y is nonzero, and c_f is zero
458 // only if it underflowed, which counts as complete cancellation).
459 let exp_y = y.floor_log_base_2_abs() + 1;
460 let exp_c = c_f
461 .get_exponent()
462 .map_or(Float::MIN_EXPONENT_I64, i64::from);
463 // |cos(y)| < 2^exp_c (up to the bracket width): heavy cancellation means y is close to an
464 // odd multiple of pi/2, where the bracket below would have to be far narrower than 2^-w.
465 if exp_c < 0 {
466 let cancel = u64::exact_from(-exp_c);
467 if cancel >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4) {
468 return trig_rational_near_zero(y, exp_y, prec, rm, extra, w, true);
469 }
470 }
471 // |c_f - cos(y_f)| <= 2^(exp_c - w) (half an ulp, doubled for safety), and |cos(y) -
472 // cos(y_f)| <= |y - y_f| <= 2^(exp_y - w)
473 let w_i = i64::exact_from(w);
474 let mut delta = Rational::power_of_2(exp_c - w_i) + Rational::power_of_2(exp_y - w_i);
475 if let Some(extra) = extra {
476 delta += Rational::power_of_2(extra);
477 }
478 let c = Rational::exact_from(&c_f);
479 if let Some(result) = round_bracket(&(&c - &delta), &(c + delta), prec, rm) {
480 return result;
481 }
482 w += increment;
483 increment = w >> 1;
484 }
485}
486
487// The least number of bits of cancellation (|cos(x)| < 2^-cancel) that sends an input to
488// `cos_near_zero`; the cancellation must also be at least prec / 16, so that the Taylor series
489// there needs only a handful of terms.
490pub(crate) const NEAR_ZERO_MIN_CANCEL: u64 = 64;
491
492// The core of `trig_near_zero` and `trig_near_zero_bracket`: an approximation m 2^shift of the tiny
493// value, with |f(x) - m 2^shift| <= 2^(abs_err + shift), computed at working precision w with pi at
494// precision p, which is raised as needed to resolve delta to w bits (and left raised, so that a
495// retry starts higher). Returns (m, abs_err, shift).
496fn trig_near_zero_approx(
497 x: &Float,
498 w: u64,
499 p: &mut u64,
500 p_hint: u64,
501 cos: bool,
502) -> (Integer, u64, i64) {
503 // |x| > 1, so its exponent is positive
504 let e = u64::exact_from(x.get_exponent().unwrap());
505 // n = round(2x / pi) for cos, or round(x / pi) for sin. Since the quotient is within 2^-62 of
506 // an integer (an odd one, for cos), 16 bits after the binary point suffice to identify it.
507 let mut x_low = Float::from_float_prec_ref(x, e + 16).0;
508 if cos {
509 x_low <<= 1u32;
510 }
511 let q = x_low.div_prec(Float::pi_prec(e + 16).0, e + 16).0;
512 let n = Integer::rounding_from(q, Nearest).0;
513 // cos(n pi/2 + delta) = -sin(delta) if n = 1 mod 4 and sin(delta) if n = 3 mod 4; sin(n pi +
514 // delta) = (-1)^n sin(delta)
515 let negate = if cos {
516 assert!(n.odd());
517 (&n).mod_power_of_2(2) == 1u32
518 } else {
519 assert_ne!(n, 0u32);
520 n.odd()
521 };
522 // x = x_sig * 2^x_exp exactly
523 let x_sig = x.significand_ref().unwrap();
524 let x_bits = x_sig.significant_bits();
525 let x_exp = i64::from(x.get_exponent().unwrap()) - i64::exact_from(x_bits);
526 loop {
527 // pi_p = pi_sig * 2^pi_exp, with |pi_p - pi| <= 2^(1 - e - p), so |n pi_p / 2 - n pi / 2| <
528 // 2^-p, since |n| < 2^e.
529 let (pi_sig, mut pi_exp) = get_z_2exp(Float::pi_prec(e + *p).0);
530 if cos {
531 pi_exp -= 1; // n pi_p / 2 = n pi_sig * 2^pi_exp
532 }
533 let d_exp = min(x_exp, pi_exp);
534 let a = Integer::from_sign_and_abs_ref(x > &0u32, x_sig) << u64::exact_from(x_exp - d_exp);
535 let b = (&n * pi_sig) << u64::exact_from(pi_exp - d_exp);
536 let d = a - b;
537 let d_neg = d < 0u32;
538 let mut d_abs = d.unsigned_abs();
539 let d_bits = d_abs.significant_bits();
540 let delta_exp = d_exp + i64::exact_from(d_bits);
541 if delta_exp + i64::exact_from(*p) <= i64::exact_from(w) {
542 let needed = u64::exact_from(i64::exact_from(w) - delta_exp + 2);
543 *p = max(
544 needed,
545 min(max(*p << 1, min(p_hint, *p << 3)), max(p_hint, needed)),
546 );
547 continue;
548 }
549 let mut d_exp = d_exp;
550 if d_bits > w {
551 let shift = d_bits - w;
552 d_abs >>= shift;
553 d_exp += i64::exact_from(shift);
554 }
555 let q = Integer::from(
556 (&d_abs).square() >> u64::exact_from(-((d_exp << 1) + i64::exact_from(w))),
557 );
558 let mut r = Integer::power_of_2(w);
559 let mut term = Integer::power_of_2(w);
560 let mut k = 1u64;
561 let mut terms = 0u64;
562 loop {
563 term *= &q;
564 term >>= w;
565 term.div_round_assign(Integer::from((k << 1) * ((k << 1) + 1)), Floor);
566 term.neg_assign();
567 if term == 0u32 {
568 break;
569 }
570 r += &term;
571 k += 1;
572 terms += 1;
573 }
574 let mut m = Integer::from(d_abs) * r;
575 if d_neg != negate {
576 m.neg_assign();
577 }
578 // the truncations of delta and of the series terms each cost a few units in the last place
579 // of m, which has w bits beyond the value's leading bit
580 return (
581 m,
582 w + 2 + (terms + 2).ceiling_log_base_2(),
583 d_exp - i64::exact_from(w),
584 );
585 }
586}
587
588// The initial precision of pi for `trig_near_zero_approx`, and the precision that resolves delta
589// when x is n pi/2 or n pi rounded to its own precision (see `trig_near_zero`).
590fn trig_near_zero_pi_precs(x: &Float, w: u64, cancel: u64) -> (u64, u64) {
591 let e = u64::exact_from(x.get_exponent().unwrap());
592 let x_bits = x.significand_ref().unwrap().significant_bits();
593 (w + cancel + 2, (x_bits + w + 2).saturating_sub(e))
594}
595
596// Computes cos(x) (if `cos` is true) or sin(x) for an x within about 2^-cancel of a zero of the
597// function, an odd multiple of pi/2 for cos or a nonzero multiple of pi for sin, so that the result
598// is below 2^-cancel in magnitude, where cancel >= 64 and cancel >= prec / 16.
599//
600// The Ziv loops in `cos_prec_round_normal_ref` and `sin_prec_round_normal_ref` would have to raise
601// their working precision by `cancel` bits to resolve such a result, and their schemes become
602// prohibitively slow long before `cancel` reaches 2^30, where the result underflows. Instead, write
603// x = n pi/2 + delta with n odd, so that cos(x) = -sin(delta) if n = 1 mod 4 and sin(delta) if n =
604// 3 mod 4, or x = n pi + delta, so that sin(x) = (-1)^n sin(delta). delta is computed exactly in
605// integer arithmetic from x and an approximation of pi, and sin(delta)/delta from its Taylor
606// series, which converges very quickly since |delta| is tiny. Everything is done in integers scaled
607// by explicit powers of 2, so values far below the exponent range are no problem, and only the
608// final `shl_prec_round` can underflow.
609//
610// This has no MPFR counterpart: MPFR's exponent range is so wide that cos and sin never underflow
611// there, and `mpfr_cos` and `mpfr_sin` simply keep raising their working precisions.
612pub(crate) fn trig_near_zero(
613 x: &Float,
614 prec: u64,
615 rm: RoundingMode,
616 cancel: u64,
617 cos: bool,
618) -> (Float, Ordering) {
619 // The working precision: delta and sin(delta) / delta are computed to w bits.
620 let w = prec + 64;
621 // The precision of pi: since |delta| < 2^(1 - cancel), delta is resolved to w bits once p
622 // exceeds w + cancel, unless delta is even smaller than the cancellation suggests. In that
623 // case, x is typically n pi/2 rounded to its own precision, so that |delta| is about 2^(e -
624 // x_bits), and p_hint is the precision that resolves that. The precision at least doubles each
625 // time, and grows by up to 8 times to reach p_hint, so that the cost of the early iterations is
626 // a small fraction of that of the last one, without wildly overshooting if x is only stored at
627 // a higher precision than the one it agrees with n pi/2 to.
628 let (mut p, p_hint) = trig_near_zero_pi_precs(x, w, cancel);
629 loop {
630 let (m, abs_err, shift) = trig_near_zero_approx(x, w, &mut p, p_hint, cos);
631 let m_bits = m.significant_bits();
632 assert!(m_bits <= const { Float::MAX_EXPONENT as u64 });
633 let err = m_bits - abs_err;
634 let s = Float::from_integer_prec(m, m_bits).0;
635 if float_can_round(s.significand_ref().unwrap(), err, prec, rm) {
636 return s.shl_prec_round(shift, prec, rm);
637 }
638 p += max(p >> 2, Limb::WIDTH);
639 }
640}
641
642// A `Rational` bracket [lo, hi] containing cos(x) or sin(x), as for `trig_near_zero`, about 2^-w
643// wide relative to the value: for a consumer that combines the tiny value with others before
644// rounding (the tangent).
645pub(crate) fn trig_near_zero_bracket(
646 x: &Float,
647 w: u64,
648 cancel: u64,
649 cos: bool,
650) -> (Rational, Rational) {
651 let (mut p, p_hint) = trig_near_zero_pi_precs(x, w, cancel);
652 let (m, abs_err, shift) = trig_near_zero_approx(x, w, &mut p, p_hint, cos);
653 let e = Integer::power_of_2(abs_err);
654 (
655 Rational::from(&m - &e) << shift,
656 Rational::from(m + e) << shift,
657 )
658}
659
660pub(crate) enum TrigStep {
661 // The working precision could not decide the result; retry at a higher one.
662 Retry,
663 // The result at the working precision, ready for the final rounding.
664 Done(Float),
665 // The input is within about 2^-cancel of a zero of the function, so the result is below
666 // 2^-cancel in magnitude and `trig_near_zero` resolves it directly.
667 NearZero(u64),
668}
669
670// One iteration of the Ziv loop at working precision `m`, which the cancellation check may raise
671// for the next iteration (the caller applies the generic increase on `Retry`). `cancel` tracks the
672// exponent of the smallest sum seen so far, so that the precision is only raised once per lost bit.
673fn cos_ziv_step(
674 x: &Float,
675 exp_x: i64,
676 prec: u64,
677 rm: RoundingMode,
678 reduce: bool,
679 k0: u64,
680 m: &mut u64,
681 cancel: &mut i64,
682) -> TrigStep {
683 // If |x| >= 4, first reduce x cmod (2*Pi) into xr, using mpfr_remainder: let e = EXP(x) >= 3,
684 // and m the target precision:
685 // ```
686 // (1) c <- 2*Pi [precision e+m-1, nearest]
687 // (2) xr <- remainder (x, c) [precision m, nearest]
688 // We have |c - 2*Pi| <= 1/2ulp(c) = 2^(3-e-m)
689 // |xr - x - k c| <= 1/2ulp(xr) <= 2^(1-m)
690 // |k| <= |x|/(2*Pi) <= 2^(e-2)
691 // Thus |xr - x - 2kPi| <= |k| |c - 2Pi| + 2^(1-m) <= 2^(2-m).
692 // It follows |cos(xr) - cos(x)| <= 2^(2-m).
693 // ```
694 let mut r = if reduce {
695 let c = Float::pi_prec(u64::exact_from(exp_x) + *m - 1).0 << 1u32; // 2Pi
696 let xr = x.ieee_remainder_prec_ref_val(c, *m).0;
697 if xr == 0u32 {
698 return TrigStep::Retry;
699 }
700 // now |xr| <= 4, thus r <= 16 below
701 xr.square_round(Ceiling).0 // err <= 1 ulp
702 } else {
703 x.square_prec_round_ref(*m, Ceiling).0 // err <= 1 ulp
704 };
705 // now |x| < 4 (or xr if reduce = 1), thus |r| <= 16 we need |r| < 1/2 for mpfr_cos2_aux, i.e.,
706 // EXP(r) - 2K <= -1
707 let exp_r = i64::from(r.get_exponent().unwrap());
708 let k = k0 + 1 + (u64::exact_from(max(0, exp_r)) >> 1);
709 // since K0 >= 0, if EXP(r) < 0, then K >= 1, thus EXP(r) - 2K <= -3; otherwise if EXP(r) >= 0,
710 // then K >= 1/2 + EXP(r)/2, thus EXP(r) - 2K <= -1
711 r >>= k << 1; // Can't overflow!
712 // s <- 1 - r/2! + ... + (-1)^l r^l/(2l)!
713 let (mut s, err_ulps) = cos2_aux(&r, *m);
714 // err_ulps is the error bound in ulps on s
715 let one = Float::one_prec(*m);
716 for _ in 0..k {
717 s.square_prec_round_assign(*m, Ceiling); // err <= 2*olderr
718 s <<= 1u32; // Can't overflow
719 s.sub_prec_assign_ref(&one, *m); // err <= 4*olderr
720 if s == 0u32 {
721 fail_on_untested_path("cos_ziv_step, s == 0 after doubling");
722 return TrigStep::Retry;
723 }
724 assert!(s.get_exponent().unwrap() <= 1);
725 }
726 // The absolute error on s is bounded by (2l+1/3)*2^(2K-m) 2l+1/3 <= 2l+1. If |x| >= 4, we need
727 // to add 2^(2-m) for the argument reduction by 2Pi: if K = 0, this amounts to add 4 to 2l+1/3,
728 // i.e., to add 2 to l; if K >= 1, this amounts to add 1 to 2*l+1/3. (K >= 1 always holds here,
729 // since K0 >= 0, so the K = 0 case in the C code is dead.)
730 let mut err_ulps = (err_ulps << 1) + 1;
731 if reduce {
732 err_ulps += 1;
733 }
734 let err_bits = err_ulps.ceiling_log_base_2() + (k << 1);
735 // now the error is bounded by 2^(err_bits-m) = 2^(EXP(s)-err)
736 let exp_s = i64::from(s.get_exponent().unwrap());
737 let err = exp_s + i64::exact_from(*m) - i64::exact_from(err_bits);
738 if err > 0 && float_can_round(s.significand_ref().unwrap(), u64::exact_from(err), prec, rm) {
739 return TrigStep::Done(s);
740 }
741 if exp_s == 1 && *m > err_bits && *m - err_bits >= prec + u64::from(rm == Nearest) {
742 // s = 1 or -1, and except x=0 which was already checked above, cos(x) cannot be 1 or -1, so
743 // we can round if the error is less than 2^(-precy) for directed rounding, or 2^(-precy-1)
744 // for rounding to nearest.
745 //
746 // If round to nearest or away, result is s = 1 or -1, otherwise it is round(nexttoward (s,
747 // 0)). However, in order to have the inexact flag correctly set below, we set |s| to 1 -
748 // 2^(-m) in all cases.
749 let neighbor = one_neighbor(*m, false);
750 return TrigStep::Done(if s < 0u32 { -neighbor } else { neighbor });
751 }
752 // |cos(x)| < 2^bound
753 let bound = max(exp_s, i64::exact_from(err_bits) - i64::exact_from(*m)) + 1;
754 if bound < 0 {
755 let c = u64::exact_from(-bound);
756 if c >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4) {
757 return TrigStep::NearZero(c);
758 }
759 }
760 if exp_s < *cancel {
761 *m += u64::exact_from(*cancel - exp_s);
762 *cancel = exp_s;
763 }
764 TrigStep::Retry
765}
766
767// This is mpfr_cos from cos.c, MPFR 4.2.2, including the `mpfr_cos_fast` tier for precisions at or
768// above `SINCOS_THRESHOLD`.
769fn cos_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
770 assert_ne!(rm, Exact, "Inexact cos");
771 // cos(x) = 1-x^2/2 + ..., so error < 2^(2*EXP(x)-1)
772 let exp_x = i64::from(x.get_exponent().unwrap());
773 // MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, __gmpfr_one, -2 * expx, 1, 0, rnd_mode, expo, {});
774 let neg_err = -(exp_x << 1);
775 if neg_err > 0 {
776 let err = u64::exact_from(neg_err) + 1;
777 if err > prec + 1 {
778 // The reference value 1 has precision 1 < err, so float_round_near_x always succeeds.
779 // The error bound only has to clear prec + 1; passing an enormous err (a tiny x has one
780 // around 2^31) would make float_round_near_x do work proportional to it.
781 return float_round_near_x(&Float::ONE, min(err, prec + 2), false, prec, rm).unwrap();
782 }
783 }
784 // Compute initial precision
785 if prec >= SINCOS_THRESHOLD {
786 return sin_cos_fast(x, prec, rm, false, true).1.unwrap();
787 }
788 cos_basic(x, exp_x, prec, rm)
789}
790
791// The basic tier of `cos_prec_round_normal_ref`: the Ziv loop of `mpfr_cos`, for a finite nonzero x
792// of exponent `exp_x` that the small-input shortcut did not settle.
793pub(crate) fn cos_basic(x: &Float, exp_x: i64, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
794 let k0 = (prec / 3).floor_sqrt();
795 let mut m = prec + (prec.ceiling_log_base_2() << 1) + (k0 << 1) + 4;
796 let reduce = exp_x >= 3;
797 let mut cancel: i64 = 0;
798 let mut increment = Limb::WIDTH;
799 let s = loop {
800 match cos_ziv_step(x, exp_x, prec, rm, reduce, k0, &mut m, &mut cancel) {
801 TrigStep::Done(s) => break s,
802 TrigStep::NearZero(c) => return trig_near_zero(x, prec, rm, c, true),
803 TrigStep::Retry => {}
804 }
805 // ziv_next: MPFR_ZIV_NEXT (loop, m);
806 m += increment;
807 increment = m >> 1;
808 };
809 Float::from_float_prec_round(s, prec, rm)
810}
811
812impl Float {
813 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result to the specified precision
814 /// and with the specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is
815 /// also returned, indicating whether the rounded cosine is less than, equal to, or greater than
816 /// the exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this
817 /// function returns a `NaN` it also returns `Equal`.
818 ///
819 /// See [`RoundingMode`] for a description of the possible rounding modes.
820 ///
821 /// $$
822 /// f(x,p,m) = \cos x+\varepsilon.
823 /// $$
824 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
825 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos
826 /// x|\rfloor-p+1}$.
827 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos
828 /// x|\rfloor-p}$.
829 ///
830 /// If the output has a precision, it is `prec`.
831 ///
832 /// Special cases:
833 /// - $f(\text{NaN},p,m)=\text{NaN}$
834 /// - $f(\pm\infty,p,m)=\text{NaN}$
835 /// - $f(\pm0.0,p,m)=1.0$
836 ///
837 /// Overflow and underflow:
838 /// - Since $|\cos x|\leq 1$, the result never overflows.
839 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
840 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
841 /// instead.
842 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
843 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
844 /// instead.
845 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
846 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
847 /// instead.
848 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
849 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
850 /// returned instead.
851 ///
852 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
853 /// more than $2^{30}$ bits of precision.
854 ///
855 /// If you know you'll be using `Nearest`, consider using [`Float::cos_prec`] instead. If you
856 /// know that your target precision is the precision of the input, consider using
857 /// [`Float::cos_round`] instead. If both of these things are true, consider using
858 /// [`Float::cos`] instead.
859 ///
860 /// # Worst-case complexity
861 /// $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))$
862 ///
863 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
864 ///
865 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
866 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
867 /// a negative one): the Taylor series at working precision $n$, summed by binary splitting for
868 /// large $n$, costs the first term, and for $|x| \geq 4$ the argument is reduced modulo $2\pi$,
869 /// which requires $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input. Unlike most
870 /// functions, `cos` therefore gets slower as the magnitude of its input grows, not just as the
871 /// precision does.
872 ///
873 /// # Panics
874 /// Panics if `rm` is `Exact`, since the cosine of a finite nonzero [`Float`] is never exactly
875 /// representable, or if `prec` is zero.
876 ///
877 /// # Examples
878 /// ```
879 /// use malachite_base::rounding_modes::RoundingMode::*;
880 /// use malachite_float::Float;
881 /// use std::cmp::Ordering::*;
882 ///
883 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
884 /// .0
885 /// .cos_prec_round(5, Floor);
886 /// assert_eq!(c.to_string(), "0.531");
887 /// assert_eq!(o, Less);
888 ///
889 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
890 /// .0
891 /// .cos_prec_round(5, Ceiling);
892 /// assert_eq!(c.to_string(), "0.562");
893 /// assert_eq!(o, Greater);
894 ///
895 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
896 /// .0
897 /// .cos_prec_round(5, Nearest);
898 /// assert_eq!(c.to_string(), "0.531");
899 /// assert_eq!(o, Less);
900 ///
901 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
902 /// .0
903 /// .cos_prec_round(20, Floor);
904 /// assert_eq!(c.to_string(), "0.54030228");
905 /// assert_eq!(o, Less);
906 ///
907 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
908 /// .0
909 /// .cos_prec_round(20, Ceiling);
910 /// assert_eq!(c.to_string(), "0.54030323");
911 /// assert_eq!(o, Greater);
912 ///
913 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
914 /// .0
915 /// .cos_prec_round(20, Nearest);
916 /// assert_eq!(c.to_string(), "0.54030228");
917 /// assert_eq!(o, Less);
918 /// ```
919 #[inline]
920 pub fn cos_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
921 self.cos_prec_round_ref(prec, rm)
922 }
923
924 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result to the specified precision
925 /// and with the specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`]
926 /// is also returned, indicating whether the rounded cosine is less than, equal to, or greater
927 /// than the exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this
928 /// function returns a `NaN` it also returns `Equal`.
929 ///
930 /// See [`RoundingMode`] for a description of the possible rounding modes.
931 ///
932 /// $$
933 /// f(x,p,m) = \cos x+\varepsilon.
934 /// $$
935 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
936 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos
937 /// x|\rfloor-p+1}$.
938 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos
939 /// x|\rfloor-p}$.
940 ///
941 /// If the output has a precision, it is `prec`.
942 ///
943 /// Special cases:
944 /// - $f(\text{NaN},p,m)=\text{NaN}$
945 /// - $f(\pm\infty,p,m)=\text{NaN}$
946 /// - $f(\pm0.0,p,m)=1.0$
947 ///
948 /// Overflow and underflow:
949 /// - Since $|\cos x|\leq 1$, the result never overflows.
950 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
951 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
952 /// instead.
953 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
954 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
955 /// instead.
956 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
957 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
958 /// instead.
959 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
960 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
961 /// returned instead.
962 ///
963 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
964 /// more than $2^{30}$ bits of precision.
965 ///
966 /// If you know you'll be using `Nearest`, consider using [`Float::cos_prec_ref`] instead. If
967 /// you know that your target precision is the precision of the input, consider using
968 /// [`Float::cos_round_ref`] instead. If both of these things are true, consider using
969 /// `(&Float).cos()` instead.
970 ///
971 /// # Worst-case complexity
972 /// $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))$
973 ///
974 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
975 ///
976 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
977 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
978 /// a negative one): the Taylor series at working precision $n$, summed by binary splitting for
979 /// large $n$, costs the first term, and for $|x| \geq 4$ the argument is reduced modulo $2\pi$,
980 /// which requires $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input. Unlike most
981 /// functions, `cos` therefore gets slower as the magnitude of its input grows, not just as the
982 /// precision does.
983 ///
984 /// # Panics
985 /// Panics if `rm` is `Exact`, since the cosine of a finite nonzero [`Float`] is never exactly
986 /// representable, or if `prec` is zero.
987 ///
988 /// # Examples
989 /// ```
990 /// use malachite_base::rounding_modes::RoundingMode::*;
991 /// use malachite_float::Float;
992 /// use std::cmp::Ordering::*;
993 ///
994 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_round_ref(5, Floor);
995 /// assert_eq!(c.to_string(), "0.531");
996 /// assert_eq!(o, Less);
997 ///
998 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_round_ref(5, Ceiling);
999 /// assert_eq!(c.to_string(), "0.562");
1000 /// assert_eq!(o, Greater);
1001 ///
1002 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_round_ref(5, Nearest);
1003 /// assert_eq!(c.to_string(), "0.531");
1004 /// assert_eq!(o, Less);
1005 ///
1006 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_round_ref(20, Floor);
1007 /// assert_eq!(c.to_string(), "0.54030228");
1008 /// assert_eq!(o, Less);
1009 ///
1010 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_round_ref(20, Ceiling);
1011 /// assert_eq!(c.to_string(), "0.54030323");
1012 /// assert_eq!(o, Greater);
1013 ///
1014 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_round_ref(20, Nearest);
1015 /// assert_eq!(c.to_string(), "0.54030228");
1016 /// assert_eq!(o, Less);
1017 /// ```
1018 pub fn cos_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
1019 assert_ne!(prec, 0);
1020 match &self.0 {
1021 NaN | Infinity { .. } => (Self::NAN, Equal),
1022 // cos(+0) = cos(-0) = 1
1023 Zero { .. } => (Self::one_prec(prec), Equal),
1024 Finite { .. } => cos_prec_round_normal_ref(self, prec, rm),
1025 }
1026 }
1027
1028 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result to the nearest value of
1029 /// the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned,
1030 /// indicating whether the rounded cosine is less than, equal to, or greater than the exact
1031 /// cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1032 /// a `NaN` it also returns `Equal`.
1033 ///
1034 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1035 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1036 /// the `Nearest` rounding mode.
1037 ///
1038 /// $$
1039 /// f(x,p) = \cos x+\varepsilon.
1040 /// $$
1041 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1042 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
1043 ///
1044 /// If the output has a precision, it is `prec`.
1045 ///
1046 /// Special cases:
1047 /// - $f(\text{NaN},p)=\text{NaN}$
1048 /// - $f(\pm\infty,p)=\text{NaN}$
1049 /// - $f(\pm0.0,p)=1.0$
1050 ///
1051 /// Overflow and underflow:
1052 /// - Since $|\cos x|\leq 1$, the result never overflows.
1053 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1054 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1055 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1056 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1057 ///
1058 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
1059 /// more than $2^{30}$ bits of precision.
1060 ///
1061 /// If you want to use a rounding mode other than `Nearest`, consider using
1062 /// [`Float::cos_prec_round`] instead. If you know that your target precision is the precision
1063 /// of the input, consider using [`Float::cos`] instead.
1064 ///
1065 /// # Worst-case complexity
1066 /// $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))$
1067 ///
1068 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1069 ///
1070 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1071 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1072 /// a negative one): the Taylor series at working precision $n$, summed by binary splitting for
1073 /// large $n$, costs the first term, and for $|x| \geq 4$ the argument is reduced modulo $2\pi$,
1074 /// which requires $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input. Unlike most
1075 /// functions, `cos` therefore gets slower as the magnitude of its input grows, not just as the
1076 /// precision does.
1077 ///
1078 /// # Panics
1079 /// Panics if `prec` is zero.
1080 ///
1081 /// # Examples
1082 /// ```
1083 /// use malachite_float::Float;
1084 /// use std::cmp::Ordering::*;
1085 ///
1086 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.cos_prec(5);
1087 /// assert_eq!(c.to_string(), "0.531");
1088 /// assert_eq!(o, Less);
1089 ///
1090 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.cos_prec(20);
1091 /// assert_eq!(c.to_string(), "0.54030228");
1092 /// assert_eq!(o, Less);
1093 /// ```
1094 #[inline]
1095 pub fn cos_prec(self, prec: u64) -> (Self, Ordering) {
1096 self.cos_prec_round(prec, Nearest)
1097 }
1098
1099 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result to the nearest value of
1100 /// the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also
1101 /// returned, indicating whether the rounded cosine is less than, equal to, or greater than the
1102 /// exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function
1103 /// returns a `NaN` it also returns `Equal`.
1104 ///
1105 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1106 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1107 /// the `Nearest` rounding mode.
1108 ///
1109 /// $$
1110 /// f(x,p) = \cos x+\varepsilon.
1111 /// $$
1112 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1113 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
1114 ///
1115 /// If the output has a precision, it is `prec`.
1116 ///
1117 /// Special cases:
1118 /// - $f(\text{NaN},p)=\text{NaN}$
1119 /// - $f(\pm\infty,p)=\text{NaN}$
1120 /// - $f(\pm0.0,p)=1.0$
1121 ///
1122 /// Overflow and underflow:
1123 /// - Since $|\cos x|\leq 1$, the result never overflows.
1124 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1125 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1126 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1127 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1128 ///
1129 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
1130 /// more than $2^{30}$ bits of precision.
1131 ///
1132 /// If you want to use a rounding mode other than `Nearest`, consider using
1133 /// [`Float::cos_prec_round_ref`] instead. If you know that your target precision is the
1134 /// precision of the input, consider using `(&Float).cos()` instead.
1135 ///
1136 /// # Worst-case complexity
1137 /// $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))$
1138 ///
1139 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1140 ///
1141 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1142 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1143 /// a negative one): the Taylor series at working precision $n$, summed by binary splitting for
1144 /// large $n$, costs the first term, and for $|x| \geq 4$ the argument is reduced modulo $2\pi$,
1145 /// which requires $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input. Unlike most
1146 /// functions, `cos` therefore gets slower as the magnitude of its input grows, not just as the
1147 /// precision does.
1148 ///
1149 /// # Panics
1150 /// Panics if `prec` is zero.
1151 ///
1152 /// # Examples
1153 /// ```
1154 /// use malachite_float::Float;
1155 /// use std::cmp::Ordering::*;
1156 ///
1157 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_ref(5);
1158 /// assert_eq!(c.to_string(), "0.531");
1159 /// assert_eq!(o, Less);
1160 ///
1161 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_prec_ref(20);
1162 /// assert_eq!(c.to_string(), "0.54030228");
1163 /// assert_eq!(o, Less);
1164 /// ```
1165 #[inline]
1166 pub fn cos_prec_ref(&self, prec: u64) -> (Self, Ordering) {
1167 self.cos_prec_round_ref(prec, Nearest)
1168 }
1169
1170 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result with the specified
1171 /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating
1172 /// whether the rounded cosine is less than, equal to, or greater than the exact cosine.
1173 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
1174 /// it also returns `Equal`.
1175 ///
1176 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
1177 /// description of the possible rounding modes.
1178 ///
1179 /// $$
1180 /// f(x,m) = \cos x+\varepsilon.
1181 /// $$
1182 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1183 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos
1184 /// x|\rfloor-p+1}$, where $p$ is the precision of the input.
1185 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos
1186 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1187 ///
1188 /// If the output has a precision, it is the precision of the input.
1189 ///
1190 /// Special cases:
1191 /// - $f(\text{NaN},m)=\text{NaN}$
1192 /// - $f(\pm\infty,m)=\text{NaN}$
1193 /// - $f(\pm0.0,m)=1.0$
1194 ///
1195 /// Overflow and underflow:
1196 /// - Since $|\cos x|\leq 1$, the result never overflows.
1197 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1198 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1199 /// instead.
1200 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1201 /// - If $2^{-2^{30}-1}<f(x,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1202 /// instead.
1203 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1204 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1205 /// instead.
1206 /// - If $-2^{-2^{30}-1}\leq f(x,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1207 /// - If $-2^{-2^{30}}<f(x,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is returned
1208 /// instead.
1209 ///
1210 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
1211 /// more than $2^{30}$ bits of precision.
1212 ///
1213 /// If you want to specify an output precision, consider using [`Float::cos_prec_round`]
1214 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1215 /// [`Float::cos`] instead.
1216 ///
1217 /// # Worst-case complexity
1218 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
1219 ///
1220 /// $M(n, e) = O((n+e) \log (n+e))$
1221 ///
1222 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
1223 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
1224 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
1225 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
1226 /// e$ bits. Unlike most functions, `cos` therefore gets slower as the magnitude of its input
1227 /// grows, not just as the precision does.
1228 ///
1229 /// # Panics
1230 /// Panics if `rm` is `Exact`, since the cosine of a finite nonzero [`Float`] is never exactly
1231 /// representable.
1232 ///
1233 /// # Examples
1234 /// ```
1235 /// use malachite_base::rounding_modes::RoundingMode::*;
1236 /// use malachite_float::Float;
1237 /// use std::cmp::Ordering::*;
1238 ///
1239 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.cos_round(Floor);
1240 /// assert_eq!(c.to_string(), "0.54030230586813971740093660744256");
1241 /// assert_eq!(o, Less);
1242 ///
1243 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.cos_round(Ceiling);
1244 /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
1245 /// assert_eq!(o, Greater);
1246 ///
1247 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.cos_round(Nearest);
1248 /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
1249 /// assert_eq!(o, Greater);
1250 /// ```
1251 #[inline]
1252 pub fn cos_round(self, rm: RoundingMode) -> (Self, Ordering) {
1253 let prec = self.significant_bits();
1254 self.cos_prec_round(prec, rm)
1255 }
1256
1257 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result with the specified
1258 /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned,
1259 /// indicating whether the rounded cosine is less than, equal to, or greater than the exact
1260 /// cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1261 /// a `NaN` it also returns `Equal`.
1262 ///
1263 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
1264 /// description of the possible rounding modes.
1265 ///
1266 /// $$
1267 /// f(x,m) = \cos x+\varepsilon.
1268 /// $$
1269 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1270 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos
1271 /// x|\rfloor-p+1}$, where $p$ is the precision of the input.
1272 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos
1273 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1274 ///
1275 /// If the output has a precision, it is the precision of the input.
1276 ///
1277 /// Special cases:
1278 /// - $f(\text{NaN},m)=\text{NaN}$
1279 /// - $f(\pm\infty,m)=\text{NaN}$
1280 /// - $f(\pm0.0,m)=1.0$
1281 ///
1282 /// Overflow and underflow:
1283 /// - Since $|\cos x|\leq 1$, the result never overflows.
1284 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1285 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1286 /// instead.
1287 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1288 /// - If $2^{-2^{30}-1}<f(x,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1289 /// instead.
1290 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1291 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1292 /// instead.
1293 /// - If $-2^{-2^{30}-1}\leq f(x,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1294 /// - If $-2^{-2^{30}}<f(x,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is returned
1295 /// instead.
1296 ///
1297 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
1298 /// more than $2^{30}$ bits of precision.
1299 ///
1300 /// If you want to specify an output precision, consider using [`Float::cos_prec_round_ref`]
1301 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1302 /// `(&Float).cos()` instead.
1303 ///
1304 /// # Worst-case complexity
1305 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
1306 ///
1307 /// $M(n, e) = O((n+e) \log (n+e))$
1308 ///
1309 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
1310 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
1311 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
1312 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
1313 /// e$ bits. Unlike most functions, `cos` therefore gets slower as the magnitude of its input
1314 /// grows, not just as the precision does.
1315 ///
1316 /// # Panics
1317 /// Panics if `rm` is `Exact`, since the cosine of a finite nonzero [`Float`] is never exactly
1318 /// representable.
1319 ///
1320 /// # Examples
1321 /// ```
1322 /// use malachite_base::rounding_modes::RoundingMode::*;
1323 /// use malachite_float::Float;
1324 /// use std::cmp::Ordering::*;
1325 ///
1326 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_round_ref(Floor);
1327 /// assert_eq!(c.to_string(), "0.54030230586813971740093660744256");
1328 /// assert_eq!(o, Less);
1329 ///
1330 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_round_ref(Ceiling);
1331 /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
1332 /// assert_eq!(o, Greater);
1333 ///
1334 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).cos_round_ref(Nearest);
1335 /// assert_eq!(c.to_string(), "0.54030230586813971740093660744335");
1336 /// assert_eq!(o, Greater);
1337 /// ```
1338 #[inline]
1339 pub fn cos_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
1340 self.cos_prec_round_ref(self.significant_bits(), rm)
1341 }
1342
1343 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result to the specified precision
1344 /// and with the specified rounding mode. The [`Float`] is replaced by the result, and an
1345 /// [`Ordering`] is returned, indicating whether the rounded cosine is less than, equal to, or
1346 /// greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever
1347 /// this function sets a `NaN` it also returns `Equal`.
1348 ///
1349 /// See [`RoundingMode`] for a description of the possible rounding modes.
1350 ///
1351 /// $$
1352 /// x \gets \cos x+\varepsilon.
1353 /// $$
1354 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1355 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos
1356 /// x|\rfloor-p+1}$.
1357 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos
1358 /// x|\rfloor-p}$.
1359 ///
1360 /// If the output has a precision, it is `prec`.
1361 ///
1362 /// See the [`Float::cos_prec_round`] documentation for information on special cases, overflow,
1363 /// and underflow.
1364 ///
1365 /// If you know you'll be using `Nearest`, consider using [`Float::cos_prec_assign`] instead. If
1366 /// you know that your target precision is the precision of the input, consider using
1367 /// [`Float::cos_round_assign`] instead. If both of these things are true, consider using
1368 /// [`Float::cos_assign`] instead.
1369 ///
1370 /// # Worst-case complexity
1371 /// $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))$
1372 ///
1373 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1374 ///
1375 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1376 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1377 /// a negative one): the Taylor series at working precision $n$, summed by binary splitting for
1378 /// large $n$, costs the first term, and for $|x| \geq 4$ the argument is reduced modulo $2\pi$,
1379 /// which requires $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input. Unlike most
1380 /// functions, `cos` therefore gets slower as the magnitude of its input grows, not just as the
1381 /// precision does.
1382 ///
1383 /// # Panics
1384 /// Panics if `rm` is `Exact`, since the cosine of a finite nonzero [`Float`] is never exactly
1385 /// representable, or if `prec` is zero.
1386 ///
1387 /// # Examples
1388 /// ```
1389 /// use malachite_base::rounding_modes::RoundingMode::*;
1390 /// use malachite_float::Float;
1391 /// use std::cmp::Ordering::*;
1392 ///
1393 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1394 /// assert_eq!(x.cos_prec_round_assign(5, Floor), Less);
1395 /// assert_eq!(x.to_string(), "0.531");
1396 ///
1397 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1398 /// assert_eq!(x.cos_prec_round_assign(5, Ceiling), Greater);
1399 /// assert_eq!(x.to_string(), "0.562");
1400 ///
1401 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1402 /// assert_eq!(x.cos_prec_round_assign(5, Nearest), Less);
1403 /// assert_eq!(x.to_string(), "0.531");
1404 ///
1405 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1406 /// assert_eq!(x.cos_prec_round_assign(20, Floor), Less);
1407 /// assert_eq!(x.to_string(), "0.54030228");
1408 ///
1409 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1410 /// assert_eq!(x.cos_prec_round_assign(20, Ceiling), Greater);
1411 /// assert_eq!(x.to_string(), "0.54030323");
1412 ///
1413 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1414 /// assert_eq!(x.cos_prec_round_assign(20, Nearest), Less);
1415 /// assert_eq!(x.to_string(), "0.54030228");
1416 /// ```
1417 #[inline]
1418 pub fn cos_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
1419 let o;
1420 (*self, o) = self.cos_prec_round_ref(prec, rm);
1421 o
1422 }
1423
1424 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result to the nearest value of
1425 /// the specified precision. The [`Float`] is replaced by the result, and an [`Ordering`] is
1426 /// returned, indicating whether the rounded cosine is less than, equal to, or greater than the
1427 /// exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function
1428 /// sets a `NaN` it also returns `Equal`.
1429 ///
1430 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1431 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1432 /// the `Nearest` rounding mode.
1433 ///
1434 /// $$
1435 /// x \gets \cos x+\varepsilon.
1436 /// $$
1437 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1438 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
1439 ///
1440 /// If the output has a precision, it is `prec`.
1441 ///
1442 /// See the [`Float::cos_prec`] documentation for information on special cases, overflow, and
1443 /// underflow.
1444 ///
1445 /// If you want to use a rounding mode other than `Nearest`, consider using
1446 /// [`Float::cos_prec_round_assign`] instead. If you know that your target precision is the
1447 /// precision of the input, consider using [`Float::cos_assign`] instead.
1448 ///
1449 /// # Worst-case complexity
1450 /// $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))$
1451 ///
1452 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1453 ///
1454 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1455 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1456 /// a negative one): the Taylor series at working precision $n$, summed by binary splitting for
1457 /// large $n$, costs the first term, and for $|x| \geq 4$ the argument is reduced modulo $2\pi$,
1458 /// which requires $\pi$ to about $n + e$ bits and a remainder of the $m$-bit input. Unlike most
1459 /// functions, `cos` therefore gets slower as the magnitude of its input grows, not just as the
1460 /// precision does.
1461 ///
1462 /// # Panics
1463 /// Panics if `prec` is zero.
1464 ///
1465 /// # Examples
1466 /// ```
1467 /// use malachite_float::Float;
1468 /// use std::cmp::Ordering::*;
1469 ///
1470 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1471 /// assert_eq!(x.cos_prec_assign(5), Less);
1472 /// assert_eq!(x.to_string(), "0.531");
1473 ///
1474 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1475 /// assert_eq!(x.cos_prec_assign(20), Less);
1476 /// assert_eq!(x.to_string(), "0.54030228");
1477 /// ```
1478 #[inline]
1479 pub fn cos_prec_assign(&mut self, prec: u64) -> Ordering {
1480 self.cos_prec_round_assign(prec, Nearest)
1481 }
1482
1483 /// Computes $\cos x$, the cosine of a [`Float`], rounding the result with the specified
1484 /// rounding mode. The [`Float`] is replaced by the result, and an [`Ordering`] is returned,
1485 /// indicating whether the rounded cosine is less than, equal to, or greater than the exact
1486 /// cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function sets a
1487 /// `NaN` it also returns `Equal`.
1488 ///
1489 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
1490 /// description of the possible rounding modes.
1491 ///
1492 /// $$
1493 /// x \gets \cos x+\varepsilon.
1494 /// $$
1495 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
1496 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos
1497 /// x|\rfloor-p+1}$, where $p$ is the precision of the input.
1498 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos
1499 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1500 ///
1501 /// If the output has a precision, it is the precision of the input.
1502 ///
1503 /// See the [`Float::cos_round`] documentation for information on special cases, overflow, and
1504 /// underflow.
1505 ///
1506 /// If you want to specify an output precision, consider using [`Float::cos_prec_round_assign`]
1507 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1508 /// [`Float::cos_assign`] instead.
1509 ///
1510 /// # Worst-case complexity
1511 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
1512 ///
1513 /// $M(n, e) = O((n+e) \log (n+e))$
1514 ///
1515 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
1516 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
1517 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
1518 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
1519 /// e$ bits. Unlike most functions, `cos` therefore gets slower as the magnitude of its input
1520 /// grows, not just as the precision does.
1521 ///
1522 /// # Panics
1523 /// Panics if `rm` is `Exact`, since the cosine of a finite nonzero [`Float`] is never exactly
1524 /// representable.
1525 ///
1526 /// # Examples
1527 /// ```
1528 /// use malachite_base::rounding_modes::RoundingMode::*;
1529 /// use malachite_float::Float;
1530 /// use std::cmp::Ordering::*;
1531 ///
1532 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1533 /// assert_eq!(x.cos_round_assign(Floor), Less);
1534 /// assert_eq!(x.to_string(), "0.54030230586813971740093660744256");
1535 ///
1536 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1537 /// assert_eq!(x.cos_round_assign(Ceiling), Greater);
1538 /// assert_eq!(x.to_string(), "0.54030230586813971740093660744335");
1539 ///
1540 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1541 /// assert_eq!(x.cos_round_assign(Nearest), Greater);
1542 /// assert_eq!(x.to_string(), "0.54030230586813971740093660744335");
1543 /// ```
1544 #[inline]
1545 pub fn cos_round_assign(&mut self, rm: RoundingMode) -> Ordering {
1546 let prec = self.significant_bits();
1547 self.cos_prec_round_assign(prec, rm)
1548 }
1549}
1550
1551impl Float {
1552 /// Computes $\cos x$, the cosine of a [`Rational`], rounding the result to the specified
1553 /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
1554 /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the
1555 /// rounded cosine is less than, equal to, or greater than the exact cosine.
1556 ///
1557 /// See [`RoundingMode`] for a description of the possible rounding modes.
1558 ///
1559 /// $$
1560 /// f(x,p,m) = \cos x+\varepsilon.
1561 /// $$
1562 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p+1}$.
1563 /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
1564 ///
1565 /// These bounds do not apply when the result underflows; see below.
1566 ///
1567 /// The output has precision `prec`.
1568 ///
1569 /// Special cases:
1570 /// - $f(0,p,m)=1$.
1571 ///
1572 /// Overflow and underflow:
1573 /// - Since $|\cos x|\leq 1$, the result never overflows.
1574 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1575 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1576 /// instead.
1577 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1578 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1579 /// instead.
1580 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1581 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1582 /// instead.
1583 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1584 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1585 /// returned instead.
1586 ///
1587 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
1588 /// more than $2^{30}$ bits.
1589 ///
1590 /// If you know you'll be using `Nearest`, consider using [`Float::cos_rational_prec`] instead.
1591 ///
1592 /// # Worst-case complexity
1593 /// $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))$
1594 ///
1595 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1596 ///
1597 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1598 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1599 /// is rounded to a working precision and the [`Float`] cosine taken there, which for $|x| \geq
1600 /// 4$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n + e$ bits.
1601 ///
1602 /// # Panics
1603 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1604 /// with the given precision (which is the case for every nonzero input).
1605 ///
1606 /// # Examples
1607 /// ```
1608 /// use malachite_base::rounding_modes::RoundingMode::*;
1609 /// use malachite_float::Float;
1610 /// use malachite_q::Rational;
1611 /// use std::cmp::Ordering::*;
1612 ///
1613 /// let (c, o) = Float::cos_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor);
1614 /// assert_eq!(c.to_string(), "0.812");
1615 /// assert_eq!(o, Less);
1616 ///
1617 /// let (c, o) = Float::cos_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1618 /// assert_eq!(c.to_string(), "0.844");
1619 /// assert_eq!(o, Greater);
1620 ///
1621 /// let (c, o) = Float::cos_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Floor);
1622 /// assert_eq!(c.to_string(), "0.82533550");
1623 /// assert_eq!(o, Less);
1624 ///
1625 /// let (c, o) = Float::cos_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Ceiling);
1626 /// assert_eq!(c.to_string(), "0.82533646");
1627 /// assert_eq!(o, Greater);
1628 /// ```
1629 #[inline]
1630 #[allow(clippy::needless_pass_by_value)]
1631 pub fn cos_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
1632 Self::cos_rational_prec_round_ref(&x, prec, rm)
1633 }
1634
1635 /// Computes $\cos x$, the cosine of a [`Rational`], rounding the result to the specified
1636 /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
1637 /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the
1638 /// rounded cosine is less than, equal to, or greater than the exact cosine.
1639 ///
1640 /// See [`RoundingMode`] for a description of the possible rounding modes.
1641 ///
1642 /// $$
1643 /// f(x,p,m) = \cos x+\varepsilon.
1644 /// $$
1645 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p+1}$.
1646 /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos x|\rfloor-p}$.
1647 ///
1648 /// These bounds do not apply when the result underflows.
1649 ///
1650 /// The output has precision `prec`.
1651 ///
1652 /// Special cases:
1653 /// - $f(0,p,m)=1$.
1654 ///
1655 /// See the [`Float::cos_rational_prec_round`] documentation for information on overflow and
1656 /// underflow.
1657 ///
1658 /// If you know you'll be using `Nearest`, consider using [`Float::cos_rational_prec_ref`]
1659 /// instead.
1660 ///
1661 /// # Worst-case complexity
1662 /// $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))$
1663 ///
1664 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1665 ///
1666 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1667 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1668 /// is rounded to a working precision and the [`Float`] cosine taken there, which for $|x| \geq
1669 /// 4$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n + e$ bits.
1670 ///
1671 /// # Panics
1672 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1673 /// with the given precision (which is the case for every nonzero input).
1674 ///
1675 /// # Examples
1676 /// ```
1677 /// use malachite_base::rounding_modes::RoundingMode::*;
1678 /// use malachite_float::Float;
1679 /// use malachite_q::Rational;
1680 /// use std::cmp::Ordering::*;
1681 ///
1682 /// let (c, o) =
1683 /// Float::cos_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Floor);
1684 /// assert_eq!(c.to_string(), "0.812");
1685 /// assert_eq!(o, Less);
1686 ///
1687 /// let (c, o) =
1688 /// Float::cos_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1689 /// assert_eq!(c.to_string(), "0.844");
1690 /// assert_eq!(o, Greater);
1691 ///
1692 /// let (c, o) =
1693 /// Float::cos_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Floor);
1694 /// assert_eq!(c.to_string(), "0.82533550");
1695 /// assert_eq!(o, Less);
1696 ///
1697 /// let (c, o) =
1698 /// Float::cos_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Ceiling);
1699 /// assert_eq!(c.to_string(), "0.82533646");
1700 /// assert_eq!(o, Greater);
1701 /// ```
1702 pub fn cos_rational_prec_round_ref(
1703 x: &Rational,
1704 prec: u64,
1705 rm: RoundingMode,
1706 ) -> (Self, Ordering) {
1707 assert_ne!(prec, 0);
1708 if *x == 0u32 {
1709 // cos(0) = 1, exactly
1710 return (Self::one_prec(prec), Equal);
1711 }
1712 cos_rational_helper(x, prec, rm)
1713 }
1714
1715 /// Computes $\cos x$, the cosine of a [`Rational`], rounding the result to the nearest value of
1716 /// the specified precision and returning the result as a [`Float`]. The [`Rational`] is taken
1717 /// by value. An [`Ordering`] is also returned, indicating whether the rounded cosine is less
1718 /// than, equal to, or greater than the exact cosine.
1719 ///
1720 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1721 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1722 /// the `Nearest` rounding mode.
1723 ///
1724 /// $$
1725 /// f(x,p) = \cos x+\varepsilon,
1726 /// $$
1727 /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos x|\rfloor-p}$ (unless the result
1728 /// underflows; see below).
1729 ///
1730 /// The output has precision `prec`.
1731 ///
1732 /// Special cases:
1733 /// - $f(0,p)=1$.
1734 ///
1735 /// Overflow and underflow:
1736 /// - Since $|\cos x|\leq 1$, the result never overflows.
1737 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1738 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1739 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1740 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1741 ///
1742 /// Underflow requires an input within $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes
1743 /// more than $2^{30}$ bits.
1744 ///
1745 /// If you want to use a rounding mode other than `Nearest`, consider using
1746 /// [`Float::cos_rational_prec_round`] instead.
1747 ///
1748 /// # Worst-case complexity
1749 /// $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))$
1750 ///
1751 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1752 ///
1753 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1754 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1755 /// is rounded to a working precision and the [`Float`] cosine taken there, which for $|x| \geq
1756 /// 4$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n + e$ bits.
1757 ///
1758 /// # Panics
1759 /// Panics if `prec` is zero.
1760 ///
1761 /// # Examples
1762 /// ```
1763 /// use malachite_float::Float;
1764 /// use malachite_q::Rational;
1765 /// use std::cmp::Ordering::*;
1766 ///
1767 /// let (c, o) = Float::cos_rational_prec(Rational::from_unsigneds(3u8, 5), 5);
1768 /// assert_eq!(c.to_string(), "0.812");
1769 /// assert_eq!(o, Less);
1770 ///
1771 /// let (c, o) = Float::cos_rational_prec(Rational::from_unsigneds(3u8, 5), 20);
1772 /// assert_eq!(c.to_string(), "0.82533550");
1773 /// assert_eq!(o, Less);
1774 /// ```
1775 #[inline]
1776 #[allow(clippy::needless_pass_by_value)]
1777 pub fn cos_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
1778 Self::cos_rational_prec_round_ref(&x, prec, Nearest)
1779 }
1780
1781 /// Computes $\cos x$, the cosine of a [`Rational`], rounding the result to the nearest value of
1782 /// the specified precision and returning the result as a [`Float`]. The [`Rational`] is taken
1783 /// by reference. An [`Ordering`] is also returned, indicating whether the rounded cosine is
1784 /// less than, equal to, or greater than the exact cosine.
1785 ///
1786 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1787 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1788 /// the `Nearest` rounding mode.
1789 ///
1790 /// $$
1791 /// f(x,p) = \cos x+\varepsilon,
1792 /// $$
1793 /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos x|\rfloor-p}$ (unless the result
1794 /// underflows).
1795 ///
1796 /// The output has precision `prec`.
1797 ///
1798 /// Special cases:
1799 /// - $f(0,p)=1$.
1800 ///
1801 /// See the [`Float::cos_rational_prec`] documentation for information on overflow and
1802 /// underflow.
1803 ///
1804 /// If you want to use a rounding mode other than `Nearest`, consider using
1805 /// [`Float::cos_rational_prec_round_ref`] instead.
1806 ///
1807 /// # Worst-case complexity
1808 /// $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))$
1809 ///
1810 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1811 ///
1812 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1813 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1814 /// is rounded to a working precision and the [`Float`] cosine taken there, which for $|x| \geq
1815 /// 4$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n + e$ bits.
1816 ///
1817 /// # Panics
1818 /// Panics if `prec` is zero.
1819 ///
1820 /// # Examples
1821 /// ```
1822 /// use malachite_float::Float;
1823 /// use malachite_q::Rational;
1824 /// use std::cmp::Ordering::*;
1825 ///
1826 /// let (c, o) = Float::cos_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 5);
1827 /// assert_eq!(c.to_string(), "0.812");
1828 /// assert_eq!(o, Less);
1829 ///
1830 /// let (c, o) = Float::cos_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 20);
1831 /// assert_eq!(c.to_string(), "0.82533550");
1832 /// assert_eq!(o, Less);
1833 /// ```
1834 #[inline]
1835 pub fn cos_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
1836 Self::cos_rational_prec_round_ref(x, prec, Nearest)
1837 }
1838}
1839
1840// Halves a correctly rounded constant, negating it if `negative`: the shift is exact, and a
1841// negative result mirrors the rounding mode and reverses the `Ordering`.
1842pub(crate) fn half_constant<F: Fn(u64, RoundingMode) -> (Float, Ordering)>(
1843 constant: F,
1844 negative: bool,
1845 prec: u64,
1846 rm: RoundingMode,
1847) -> (Float, Ordering) {
1848 let (c, o) = signed_constant(constant, negative, prec, rm);
1849 (c >> 1u32, o)
1850}
1851
1852// `constant` rounded to `prec` with `rm`, negated if `negative`; the negative case reuses the
1853// positive one with the rounding mode mirrored.
1854pub(crate) fn signed_constant<F: Fn(u64, RoundingMode) -> (Float, Ordering)>(
1855 constant: F,
1856 negative: bool,
1857 prec: u64,
1858 rm: RoundingMode,
1859) -> (Float, Ordering) {
1860 if negative {
1861 let (c, o) = constant(prec, -rm);
1862 (-c, o.reverse())
1863 } else {
1864 constant(prec, rm)
1865 }
1866}
1867
1868// phi - 1 = 1/phi, correctly rounded to `prec` bits: phi rounded to `prec + 1` bits, minus 1, has
1869// exactly `prec` bits, and the rounding carries over since phi - 1 lies in [1/2, 1).
1870pub(crate) fn phi_minus_1_prec_round(prec: u64, rm: RoundingMode) -> (Float, Ordering) {
1871 let (phi, o) = Float::phi_prec_round(prec + 1, rm);
1872 let (r, o_sub) = phi.sub_prec_round(Float::ONE, prec, Exact);
1873 assert_eq!(o_sub, Equal);
1874 (r, o)
1875}
1876
1877// The closed-form cases of cos(2 pi x / u), keyed by the denominator d of x/u in lowest terms (with
1878// |x| < u, so the numerator n is the angle in units of 1/d of a turn). MPFR's exact cases are (a) d
1879// dividing 4, where the cosine is 0 (always +0, following IEEE 754-2019's cosPi), 1, or -1, and (b)
1880// d = 3 or 6, where it is 1/2 or -1/2. Beyond MPFR, the algebraic cases are dispatched to a single
1881// correctly rounded constant: d = 8 gives sqrt(2)/2, d = 12 gives sqrt(3)/2, and d = 5 and 10 give
1882// phi/2 or (phi - 1)/2, up to sign. Those are 15 to 130 times faster than pi plus a cosine at the
1883// working precision, and are never exact, so they return `None` for `Exact`.
1884pub(crate) fn cos_turns_special_case(
1885 q: &Rational,
1886 prec: u64,
1887 rm: RoundingMode,
1888) -> Option<(Float, Ordering)> {
1889 let d = q.denominator_ref();
1890 if *d > 12u32 {
1891 return None;
1892 }
1893 let d = u64::exact_from(d);
1894 // the angle in units of 1/d of a turn
1895 let n = u64::exact_from(&Integer::from(q.numerator_ref()).mod_op(Integer::from(d)));
1896 match d {
1897 1 => Some((Float::one_prec(prec), Equal)),
1898 2 => Some((-Float::one_prec(prec), Equal)),
1899 4 => Some((Float::ZERO, Equal)),
1900 // cos(60°) = cos(300°) = 1/2; cos(120°) = cos(240°) = -1/2
1901 6 => Some((Float::one_prec(prec) >> 1u32, Equal)),
1902 3 => Some((-(Float::one_prec(prec) >> 1u32), Equal)),
1903 _ if rm == Exact => None,
1904 // cos(45°) = sqrt(2)/2, cos(135°) = -sqrt(2)/2
1905 8 => Some(half_constant(
1906 Float::sqrt_2_prec_round,
1907 n == 3 || n == 5,
1908 prec,
1909 rm,
1910 )),
1911 // cos(30°) = sqrt(3)/2, cos(150°) = -sqrt(3)/2
1912 12 => Some(half_constant(
1913 |prec, rm| const { Float::const_from_unsigned(3) }.sqrt_prec_round(prec, rm),
1914 n == 5 || n == 7,
1915 prec,
1916 rm,
1917 )),
1918 // cos(72°) = (phi - 1)/2, cos(144°) = -phi/2
1919 5 => Some(if n == 1 || n == 4 {
1920 half_constant(phi_minus_1_prec_round, false, prec, rm)
1921 } else {
1922 half_constant(Float::phi_prec_round, true, prec, rm)
1923 }),
1924 // cos(36°) = phi/2, cos(108°) = -(phi - 1)/2
1925 10 => Some(if n == 1 || n == 9 {
1926 half_constant(Float::phi_prec_round, false, prec, rm)
1927 } else {
1928 half_constant(phi_minus_1_prec_round, true, prec, rm)
1929 }),
1930 _ => None,
1931 }
1932}
1933
1934// cos(2 pi q) (if `cos` is true) or sin(2 pi q) for a fraction of a turn q within about 2^-64 of a
1935// zero of the function, an odd multiple of 1/4 for cos or a multiple of 1/2 for sin, where the
1936// result is tiny. Since q is rational, so is its distance d to the nearest such point, which is
1937// computed exactly; then cos(2 pi q) = -sin(2 pi d) if the point is m/4 with m = 1 mod 4 and sin(2
1938// pi d) if m = 3 mod 4, or sin(2 pi q) = (-1)^m sin(2 pi d) for the point m/2, and sin is bracketed
1939// by partial sums of its series with pi bracketed at w bits. The bracket is rounded in `Rational`
1940// arithmetic, so the result underflows correctly when it must. Returns `None` if q is not near such
1941// a point after all.
1942//
1943// This has no MPFR counterpart: MPFR's exponent range is so wide that cosu and sinu never underflow
1944// there, and they simply keep raising their working precision. The distance d from a fraction of a
1945// turn q to the nearest zero of the function, and whether the value is the negative of sin(2 pi d);
1946// `None` if q is not near such a zero after all.
1947fn trig_turns_near_zero_reduce(q: &Rational, cos: bool) -> Option<(bool, Rational)> {
1948 Some(if cos {
1949 let m = Integer::rounding_from(q << 2u32, Nearest).0;
1950 if m.even() {
1951 fail_on_untested_path("trig_turns_near_zero, not near an odd multiple of 1/4");
1952 return None;
1953 }
1954 (
1955 (&m).mod_power_of_2(2) == 1u32,
1956 q - (Rational::from(m) >> 2u32),
1957 )
1958 } else {
1959 let m = Integer::rounding_from(q << 1u32, Nearest).0;
1960 (m.odd(), q - (Rational::from(m) >> 1u32))
1961 })
1962}
1963
1964// One bracket of `trig_turns_near_zero` at working precision w, with pi bracketed to w bits.
1965fn trig_turns_near_zero_step(negate: bool, d: &Rational, w: u64) -> Option<(Rational, Rational)> {
1966 // pi_lo <= pi <= pi_lo + 2^(2 - w)
1967 let pi_lo = Rational::exact_from(&Float::pi_prec_round(w, Floor).0);
1968 let pi_hi = &pi_lo + Rational::power_of_2(2 - i64::exact_from(w));
1969 let two_d = d << 1u32;
1970 let (t_lo, t_hi) = if two_d >= 0u32 {
1971 (&two_d * pi_lo, two_d * pi_hi)
1972 } else {
1973 (&two_d * pi_hi, two_d * pi_lo)
1974 };
1975 if t_hi.ge_abs(&1u32) || t_lo.ge_abs(&1u32) {
1976 fail_on_untested_path("trig_turns_near_zero, distance not small");
1977 return None;
1978 }
1979 // sin is increasing on [t_lo, t_hi] (a subset of [-1, 1]), so sin(2 pi d) lies between
1980 // sin(t_lo) and sin(t_hi)
1981 let sin_lo = sin_bound(&t_lo, w, false);
1982 let sin_hi = sin_bound(&t_hi, w, true);
1983 Some(if negate {
1984 (-sin_hi, -sin_lo)
1985 } else {
1986 (sin_lo, sin_hi)
1987 })
1988}
1989
1990pub(crate) fn trig_turns_near_zero(
1991 q: &Rational,
1992 prec: u64,
1993 rm: RoundingMode,
1994 cos: bool,
1995) -> Option<(Float, Ordering)> {
1996 let (negate, d) = trig_turns_near_zero_reduce(q, cos)?;
1997 let mut w = prec + 64;
1998 loop {
1999 let (lo, hi) = trig_turns_near_zero_step(negate, &d, w)?;
2000 if let Some(result) = round_bracket(&lo, &hi, prec, rm) {
2001 return Some(result);
2002 }
2003 w <<= 1;
2004 }
2005}
2006
2007// The bracket of `trig_turns_near_zero`, tightened until it is narrower than 2^-(target + 4)
2008// relative to the value: for a consumer that combines the tiny value with others before rounding
2009// (the tangent).
2010pub(crate) fn trig_turns_near_zero_bracket(
2011 q: &Rational,
2012 target: u64,
2013 cos: bool,
2014) -> Option<(Rational, Rational)> {
2015 let (negate, d) = trig_turns_near_zero_reduce(q, cos)?;
2016 let mut w = target + 64;
2017 loop {
2018 let (lo, hi) = trig_turns_near_zero_step(negate, &d, w)?;
2019 if (&hi - &lo) << (target + 4) <= (&lo).abs() {
2020 return Some((lo, hi));
2021 }
2022 w <<= 1;
2023 }
2024}
2025
2026// Computes cos(2 pi x / u) for a finite nonzero `Float` x and a nonzero u, rounded to precision
2027// `prec` with rounding mode `rm`. `rm` may be `Exact` only in the exact cases (see
2028// `cos_turns_special_case`).
2029//
2030// This is mpfr_cosu from cosu.c, MPFR 4.2.2, with the additional near-zero path.
2031pub(crate) fn cos_with_period_prec_round_normal_ref(
2032 x: &Float,
2033 u: u64,
2034 prec: u64,
2035 rm: RoundingMode,
2036) -> (Float, Ordering) {
2037 // Range reduction. We do not need to reduce the argument if it is already reduced (|x| < u).
2038 // Note that the case |x| = u is better in the "else" branch as it will give xr = 0.
2039 let xr;
2040 let xp = if x.lt_abs(&u) {
2041 x
2042 } else {
2043 // xr = x mod u, with the sign of x, exactly: its precision is the size of u plus the length
2044 // of the fractional part of x.
2045 let p = i64::exact_from(x.get_prec().unwrap()) - i64::from(x.get_exponent().unwrap());
2046 let (r, o) =
2047 x.rem_unsigned_prec_round_ref(u, u64::WIDTH + u64::exact_from(max(p, 0)), Exact);
2048 assert_eq!(o, Equal);
2049 if r == 0u32 {
2050 return (Float::one_prec(prec), Equal);
2051 }
2052 xr = r;
2053 &xr
2054 };
2055 // now |xp/u| < 1; fold it into [-1/2, 1/2], exactly, so that an x just below a multiple of u
2056 // lands near 0 rather than near 1, where the small-input shortcut below applies (the cosine is
2057 // even, so the sign is immaterial; otherwise the working precision would have to grow to the
2058 // whole cancellation in 1 - cos)
2059 let xf;
2060 let xp = if (xp << 1u32).gt_abs(&u) {
2061 let p = i64::exact_from(xp.get_prec().unwrap()) - i64::from(xp.get_exponent().unwrap());
2062 let step = if *xp > 0u32 {
2063 -Float::from(u)
2064 } else {
2065 Float::from(u)
2066 };
2067 let (f, o) = xp.add_prec_ref_val(step, u64::WIDTH + u64::exact_from(max(p, 0)));
2068 if o != Equal {
2069 // The precision suffices, so the difference underflowed: x is within 2^(-2^30) of a
2070 // multiple of u, and the cosine rounds from 1 alone (and is not exact).
2071 assert_ne!(rm, Exact, "Inexact cos_with_period");
2072 return float_round_near_x(&Float::ONE, prec + 2, false, prec, rm).unwrap();
2073 }
2074 xf = f;
2075 &xf
2076 } else {
2077 xp
2078 };
2079 // for x small, we have |cos(2*pi*x/u)-1| < 1/2*(2*pi*x/u)^2 < 2^5*(x/u)^2
2080 let exp_x = i64::from(xp.get_exponent().unwrap());
2081 let log2u = if u == 1 {
2082 0
2083 } else {
2084 i64::exact_from(u.ceiling_log_base_2()) - 1
2085 };
2086 // u >= 2^log2u thus 1/u <= 2^(-log2u)
2087 let erra = -(exp_x << 1);
2088 let errb = 5 - (log2u << 1);
2089 // MPFR_SMALL_INPUT_AFTER_SAVE_EXPO (y, __gmpfr_one, erra - errb, 0, 0, rnd_mode, expo, ..)
2090 if erra > errb {
2091 let err = u64::exact_from(erra - errb);
2092 if err > prec + 1 {
2093 // The reference value 1 has precision 1 < err, so float_round_near_x always succeeds.
2094 // The error bound only has to clear prec + 1; passing an enormous err (a tiny x has one
2095 // around 2^31) would make float_round_near_x do work proportional to it. Such a tiny x
2096 // is never a special case, and its cosine is never exact.
2097 assert_ne!(rm, Exact, "Inexact cos_with_period");
2098 return float_round_near_x(&Float::ONE, min(err, prec + 2), false, prec, rm).unwrap();
2099 }
2100 }
2101 // The special cases need |x/u| >= 1/12, so the exponent test skips the `Rational` construction
2102 // for the small x that would make it expensive (a tiny x has a huge power-of-2 denominator).
2103 if exp_x >= i64::exact_from(u.significant_bits()) - 4
2104 && let Some(result) =
2105 cos_turns_special_case(&(Rational::exact_from(xp) / Rational::from(u)), prec, rm)
2106 {
2107 return result;
2108 }
2109 // Only the exact cases can be rounded exactly
2110 assert_ne!(rm, Exact, "Inexact cos_with_period");
2111 // For x large, since argument reduction is expensive, we want to avoid any failure in Ziv's
2112 // strategy, thus we take into account expx too.
2113 let mut prec_t =
2114 prec + u64::exact_from(max(exp_x, i64::exact_from(prec.ceiling_log_base_2()))) + 8;
2115 let mut increment = Limb::WIDTH;
2116 let u_float = Float::from(u);
2117 loop {
2118 // We first compute an approximation t of 2*pi*x/u, then call cos(t). If t = 2*pi*x/u + s,
2119 // then |cos(t) - cos(2*pi*x/u)| <= |s|. t = 2*pi * (1 + theta1) where |theta1| <= 2^-prec
2120 let mut t = Float::pi_prec(prec_t).0 << 1u32;
2121 // t = 2*pi*x * (1 + theta2)^2 where |theta2| <= 2^-prec
2122 t.mul_prec_assign_ref(xp, prec_t);
2123 // t = 2*pi*x/u * (1 + theta3)^3 where |theta3| <= 2^-prec
2124 t.div_prec_assign_ref(&u_float, prec_t);
2125 // if t is zero here, it means the division by u underflowed
2126 if t == 0u32 {
2127 // Unreachable in practice: such an x is caught by the small-input shortcut above unless
2128 // `prec` exceeds 2^31 bits.
2129 fail_on_untested_path(
2130 "cos_with_period_prec_round_normal_ref, division by u underflowed",
2131 );
2132 return match rm {
2133 Floor | Down => (one_neighbor(prec, false), Less),
2134 _ => (Float::one_prec(prec), Greater),
2135 };
2136 }
2137 // since prec >= 2, |(1 + theta3)^3 - 1| <= 4*theta3 <= 2^(2-prec)
2138 let exp_t = i64::from(t.get_exponent().unwrap());
2139 // we have |s| <= 2^(expt + 2 - prec)
2140 let prec_t_i = i64::exact_from(prec_t);
2141 let mut err = exp_t + 2 - prec_t_i;
2142 t.cos_prec_assign(prec_t);
2143 // A tiny (or underflowed) cosine means x/u is close to an odd multiple of 1/4, which the
2144 // near-zero path resolves exactly; the Ziv loop would need its precision raised by the
2145 // whole cancellation.
2146 let exp_t = t.get_exponent().map_or(Float::MIN_EXPONENT_I64, i64::from);
2147 if exp_t < 0 {
2148 let cancel = u64::exact_from(-exp_t);
2149 if cancel >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4)
2150 && let Some(result) = trig_turns_near_zero(
2151 &(Rational::exact_from(xp) / Rational::from(u)),
2152 prec,
2153 rm,
2154 true,
2155 )
2156 {
2157 return result;
2158 }
2159 }
2160 // the total error is at most 2^err + ulp(t)/2 = 2^err + 2^(expt-prec-1) thus if err <=
2161 // expt-prec-1, it is bounded by 2^(expt-prec), otherwise it is bounded by 2^(err+1).
2162 err = if err < exp_t - prec_t_i {
2163 exp_t - prec_t_i
2164 } else {
2165 err + 1
2166 };
2167 // normalize err for mpfr_can_round
2168 err = exp_t - err;
2169 if err > 0 && float_can_round(t.significand_ref().unwrap(), u64::exact_from(err), prec, rm)
2170 {
2171 return Float::from_float_prec_round(t, prec, rm);
2172 }
2173 // (MPFR checks its exact cases here, after the first level of Ziv's strategy; the special
2174 // cases above cover them before the loop, since the check is cheap.)
2175 prec_t += increment;
2176 increment = prec_t >> 1;
2177 }
2178}
2179
2180impl Float {
2181 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2182 /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
2183 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded cosine is
2184 /// less than, equal to, or greater than the exact cosine. Although `NaN`s are not comparable to
2185 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2186 ///
2187 /// See [`RoundingMode`] for a description of the possible rounding modes.
2188 ///
2189 /// $$
2190 /// f(x,u,p,m) = \cos(2\pi x/u)+\varepsilon.
2191 /// $$
2192 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2193 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
2194 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$.
2195 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
2196 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$.
2197 ///
2198 /// If the output has a precision, it is `prec`.
2199 ///
2200 /// Special cases:
2201 /// - $f(\text{NaN},u,p,m)=\text{NaN}$
2202 /// - $f(\pm\infty,u,p,m)=\text{NaN}$
2203 /// - $f(x,0,p,m)=\text{NaN}$
2204 /// - $f(\pm0.0,u,p,m)=1.0$
2205 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
2206 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
2207 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
2208 /// $-1/2$.
2209 ///
2210 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
2211 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
2212 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
2213 ///
2214 /// Overflow and underflow:
2215 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
2216 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
2217 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
2218 /// instead.
2219 /// - If $0<f(x,u,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
2220 /// - If $2^{-2^{30}-1}<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
2221 /// instead.
2222 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
2223 /// instead.
2224 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
2225 /// instead.
2226 /// - If $-2^{-2^{30}-1}\leq f(x,u,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
2227 /// - If $-2^{-2^{30}}<f(x,u,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
2228 /// returned instead.
2229 ///
2230 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
2231 /// which takes more than $2^{30}$ bits of precision.
2232 ///
2233 /// If you know you'll be using `Nearest`, consider using [`Float::cos_with_period_prec`]
2234 /// instead. If you know that your target precision is the precision of the input, consider
2235 /// using [`Float::cos_with_period_round`] instead.
2236 ///
2237 /// # Worst-case complexity
2238 /// $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))$
2239 ///
2240 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
2241 ///
2242 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
2243 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
2244 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
2245 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
2246 /// bits.
2247 ///
2248 /// # Panics
2249 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2250 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or
2251 /// $x$ is zero or not finite, or $u$ is zero).
2252 ///
2253 /// # Examples
2254 /// ```
2255 /// use malachite_base::num::basic::traits::One;
2256 /// use malachite_base::rounding_modes::RoundingMode::*;
2257 /// use malachite_float::Float;
2258 /// use std::cmp::Ordering::*;
2259 ///
2260 /// let (c, o) = Float::ONE.cos_with_period_prec_round(7, 10, Floor);
2261 /// assert_eq!(c.to_string(), "0.62305");
2262 /// assert_eq!(o, Less);
2263 ///
2264 /// let (c, o) = Float::ONE.cos_with_period_prec_round(7, 10, Ceiling);
2265 /// assert_eq!(c.to_string(), "0.62402");
2266 /// assert_eq!(o, Greater);
2267 ///
2268 /// let (c, o) = Float::ONE.cos_with_period_prec_round(7, 10, Nearest);
2269 /// assert_eq!(c.to_string(), "0.62305");
2270 /// assert_eq!(o, Less);
2271 ///
2272 /// // a sixth of a turn is exact
2273 /// let (c, o) = Float::from(60u32).cos_with_period_prec_round(360, 10, Exact);
2274 /// assert_eq!(c.to_string(), "0.50000");
2275 /// assert_eq!(o, Equal);
2276 ///
2277 /// // a quarter turn is exactly zero
2278 /// let (c, o) = Float::from(90u32).cos_with_period_prec_round(360, 10, Nearest);
2279 /// assert_eq!(c.to_string(), "0.0");
2280 /// assert_eq!(o, Equal);
2281 /// ```
2282 #[inline]
2283 pub fn cos_with_period_prec_round(
2284 self,
2285 u: u64,
2286 prec: u64,
2287 rm: RoundingMode,
2288 ) -> (Self, Ordering) {
2289 self.cos_with_period_prec_round_ref(u, prec, rm)
2290 }
2291
2292 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2293 /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
2294 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded cosine
2295 /// is less than, equal to, or greater than the exact cosine. Although `NaN`s are not comparable
2296 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2297 ///
2298 /// See [`RoundingMode`] for a description of the possible rounding modes.
2299 ///
2300 /// $$
2301 /// f(x,u,p,m) = \cos(2\pi x/u)+\varepsilon.
2302 /// $$
2303 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2304 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
2305 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$.
2306 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
2307 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$.
2308 ///
2309 /// If the output has a precision, it is `prec`.
2310 ///
2311 /// Special cases:
2312 /// - $f(\text{NaN},u,p,m)=\text{NaN}$
2313 /// - $f(\pm\infty,u,p,m)=\text{NaN}$
2314 /// - $f(x,0,p,m)=\text{NaN}$
2315 /// - $f(\pm0.0,u,p,m)=1.0$
2316 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
2317 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
2318 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
2319 /// $-1/2$.
2320 ///
2321 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
2322 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
2323 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
2324 ///
2325 /// Overflow and underflow:
2326 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
2327 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
2328 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
2329 /// instead.
2330 /// - If $0<f(x,u,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
2331 /// - If $2^{-2^{30}-1}<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
2332 /// instead.
2333 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
2334 /// instead.
2335 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
2336 /// instead.
2337 /// - If $-2^{-2^{30}-1}\leq f(x,u,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
2338 /// - If $-2^{-2^{30}}<f(x,u,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
2339 /// returned instead.
2340 ///
2341 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
2342 /// which takes more than $2^{30}$ bits of precision.
2343 ///
2344 /// If you know you'll be using `Nearest`, consider using [`Float::cos_with_period_prec_ref`]
2345 /// instead. If you know that your target precision is the precision of the input, consider
2346 /// using [`Float::cos_with_period_round_ref`] instead.
2347 ///
2348 /// # Worst-case complexity
2349 /// $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))$
2350 ///
2351 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
2352 ///
2353 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
2354 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
2355 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
2356 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
2357 /// bits.
2358 ///
2359 /// # Panics
2360 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2361 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or
2362 /// $x$ is zero or not finite, or $u$ is zero).
2363 ///
2364 /// # Examples
2365 /// ```
2366 /// use malachite_base::num::basic::traits::One;
2367 /// use malachite_base::rounding_modes::RoundingMode::*;
2368 /// use malachite_float::Float;
2369 /// use std::cmp::Ordering::*;
2370 ///
2371 /// let (c, o) = (&Float::ONE).cos_with_period_prec_round_ref(7, 10, Floor);
2372 /// assert_eq!(c.to_string(), "0.62305");
2373 /// assert_eq!(o, Less);
2374 ///
2375 /// let (c, o) = (&Float::ONE).cos_with_period_prec_round_ref(7, 10, Ceiling);
2376 /// assert_eq!(c.to_string(), "0.62402");
2377 /// assert_eq!(o, Greater);
2378 ///
2379 /// let (c, o) = (&Float::ONE).cos_with_period_prec_round_ref(7, 10, Nearest);
2380 /// assert_eq!(c.to_string(), "0.62305");
2381 /// assert_eq!(o, Less);
2382 ///
2383 /// // a sixth of a turn is exact
2384 /// let (c, o) = (&Float::from(60u32)).cos_with_period_prec_round_ref(360, 10, Exact);
2385 /// assert_eq!(c.to_string(), "0.50000");
2386 /// assert_eq!(o, Equal);
2387 ///
2388 /// // a quarter turn is exactly zero
2389 /// let (c, o) = (&Float::from(90u32)).cos_with_period_prec_round_ref(360, 10, Nearest);
2390 /// assert_eq!(c.to_string(), "0.0");
2391 /// assert_eq!(o, Equal);
2392 /// ```
2393 pub fn cos_with_period_prec_round_ref(
2394 &self,
2395 u: u64,
2396 prec: u64,
2397 rm: RoundingMode,
2398 ) -> (Self, Ordering) {
2399 assert_ne!(prec, 0);
2400 match &self.0 {
2401 // for u=0, return NaN
2402 _ if u == 0 => (Self::NAN, Equal),
2403 NaN | Infinity { .. } => (Self::NAN, Equal),
2404 // x is zero: cos(0) = 1
2405 Zero { .. } => (Self::one_prec(prec), Equal),
2406 Finite { .. } => cos_with_period_prec_round_normal_ref(self, u, prec, rm),
2407 }
2408 }
2409
2410 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2411 /// the result to the nearest value of the specified precision. The [`Float`] is taken by value.
2412 /// An [`Ordering`] is also returned, indicating whether the rounded cosine is less than, equal
2413 /// to, or greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`],
2414 /// whenever this function returns a `NaN` it also returns `Equal`.
2415 ///
2416 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
2417 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
2418 /// the `Nearest` rounding mode.
2419 ///
2420 /// $$
2421 /// f(x,u,p) = \cos(2\pi x/u)+\varepsilon.
2422 /// $$
2423 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2424 /// - If $x$ is finite and $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi
2425 /// x/u)|\rfloor-p}$.
2426 ///
2427 /// If the output has a precision, it is `prec`.
2428 ///
2429 /// Special cases:
2430 /// - $f(\text{NaN},u,p)=\text{NaN}$
2431 /// - $f(\pm\infty,u,p)=\text{NaN}$
2432 /// - $f(x,0,p)=\text{NaN}$
2433 /// - $f(\pm0.0,u,p)=1.0$
2434 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
2435 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
2436 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
2437 /// $-1/2$.
2438 ///
2439 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
2440 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
2441 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
2442 ///
2443 /// Overflow and underflow:
2444 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
2445 /// - If $0<f(x,u,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
2446 /// - If $2^{-2^{30}-1}<f(x,u,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
2447 /// - If $-2^{-2^{30}-1}\leq f(x,u,p)<0$, $-0.0$ is returned instead.
2448 /// - If $-2^{-2^{30}}<f(x,u,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
2449 ///
2450 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
2451 /// which takes more than $2^{30}$ bits of precision.
2452 ///
2453 /// If you want to use a rounding mode other than `Nearest`, consider using
2454 /// [`Float::cos_with_period_prec_round`] instead. If you know that your target precision is the
2455 /// precision of the input, consider using [`Float::cos_with_period_round`] with `Nearest`
2456 /// instead.
2457 ///
2458 /// # Worst-case complexity
2459 /// $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))$
2460 ///
2461 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
2462 ///
2463 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
2464 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
2465 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
2466 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
2467 /// bits.
2468 ///
2469 /// # Panics
2470 /// Panics if `prec` is zero.
2471 ///
2472 /// # Examples
2473 /// ```
2474 /// use malachite_base::num::basic::traits::One;
2475 /// use malachite_float::Float;
2476 /// use std::cmp::Ordering::*;
2477 ///
2478 /// let (c, o) = Float::ONE.cos_with_period_prec(7, 10);
2479 /// assert_eq!(c.to_string(), "0.62305");
2480 /// assert_eq!(o, Less);
2481 ///
2482 /// let (c, o) = Float::ONE.cos_with_period_prec(360, 53);
2483 /// assert_eq!(c.to_string(), "0.99984769515639127");
2484 /// assert_eq!(o, Greater);
2485 ///
2486 /// // an eighth of a turn: sqrt(2)/2
2487 /// let (c, o) = Float::ONE.cos_with_period_prec(8, 10);
2488 /// assert_eq!(c.to_string(), "0.70703");
2489 /// assert_eq!(o, Less);
2490 /// ```
2491 #[inline]
2492 pub fn cos_with_period_prec(self, u: u64, prec: u64) -> (Self, Ordering) {
2493 self.cos_with_period_prec_round(u, prec, Nearest)
2494 }
2495
2496 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2497 /// the result to the nearest value of the specified precision. The [`Float`] is taken by
2498 /// reference. An [`Ordering`] is also returned, indicating whether the rounded cosine is less
2499 /// than, equal to, or greater than the exact cosine. Although `NaN`s are not comparable to any
2500 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2501 ///
2502 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
2503 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
2504 /// the `Nearest` rounding mode.
2505 ///
2506 /// $$
2507 /// f(x,u,p) = \cos(2\pi x/u)+\varepsilon.
2508 /// $$
2509 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2510 /// - If $x$ is finite and $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi
2511 /// x/u)|\rfloor-p}$.
2512 ///
2513 /// If the output has a precision, it is `prec`.
2514 ///
2515 /// Special cases:
2516 /// - $f(\text{NaN},u,p)=\text{NaN}$
2517 /// - $f(\pm\infty,u,p)=\text{NaN}$
2518 /// - $f(x,0,p)=\text{NaN}$
2519 /// - $f(\pm0.0,u,p)=1.0$
2520 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
2521 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
2522 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
2523 /// $-1/2$.
2524 ///
2525 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
2526 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
2527 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
2528 ///
2529 /// Overflow and underflow:
2530 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
2531 /// - If $0<f(x,u,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
2532 /// - If $2^{-2^{30}-1}<f(x,u,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
2533 /// - If $-2^{-2^{30}-1}\leq f(x,u,p)<0$, $-0.0$ is returned instead.
2534 /// - If $-2^{-2^{30}}<f(x,u,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
2535 ///
2536 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
2537 /// which takes more than $2^{30}$ bits of precision.
2538 ///
2539 /// If you want to use a rounding mode other than `Nearest`, consider using
2540 /// [`Float::cos_with_period_prec_round_ref`] instead. If you know that your target precision is
2541 /// the precision of the input, consider using [`Float::cos_with_period_round_ref`] with
2542 /// `Nearest` instead.
2543 ///
2544 /// # Worst-case complexity
2545 /// $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))$
2546 ///
2547 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
2548 ///
2549 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
2550 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
2551 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
2552 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
2553 /// bits.
2554 ///
2555 /// # Panics
2556 /// Panics if `prec` is zero.
2557 ///
2558 /// # Examples
2559 /// ```
2560 /// use malachite_base::num::basic::traits::One;
2561 /// use malachite_float::Float;
2562 /// use std::cmp::Ordering::*;
2563 ///
2564 /// let (c, o) = (&Float::ONE).cos_with_period_prec_ref(7, 10);
2565 /// assert_eq!(c.to_string(), "0.62305");
2566 /// assert_eq!(o, Less);
2567 ///
2568 /// let (c, o) = (&Float::ONE).cos_with_period_prec_ref(360, 53);
2569 /// assert_eq!(c.to_string(), "0.99984769515639127");
2570 /// assert_eq!(o, Greater);
2571 ///
2572 /// // an eighth of a turn: sqrt(2)/2
2573 /// let (c, o) = (&Float::ONE).cos_with_period_prec_ref(8, 10);
2574 /// assert_eq!(c.to_string(), "0.70703");
2575 /// assert_eq!(o, Less);
2576 /// ```
2577 #[inline]
2578 pub fn cos_with_period_prec_ref(&self, u: u64, prec: u64) -> (Self, Ordering) {
2579 self.cos_with_period_prec_round_ref(u, prec, Nearest)
2580 }
2581
2582 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2583 /// the result with the specified rounding mode. The [`Float`] is taken by value. An
2584 /// [`Ordering`] is also returned, indicating whether the rounded cosine is less than, equal to,
2585 /// or greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`],
2586 /// whenever this function returns a `NaN` it also returns `Equal`.
2587 ///
2588 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
2589 /// description of the possible rounding modes.
2590 ///
2591 /// $$
2592 /// f(x,u,m) = \cos(2\pi x/u)+\varepsilon.
2593 /// $$
2594 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2595 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
2596 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$, where $p$ is the precision of the input.
2597 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
2598 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$, where $p$ is the precision of the input.
2599 ///
2600 /// If the output has a precision, it is the precision of the input.
2601 ///
2602 /// Special cases:
2603 /// - $f(\text{NaN},u,m)=\text{NaN}$
2604 /// - $f(\pm\infty,u,m)=\text{NaN}$
2605 /// - $f(x,0,m)=\text{NaN}$
2606 /// - $f(\pm0.0,u,m)=1.0$
2607 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
2608 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
2609 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
2610 /// $-1/2$.
2611 ///
2612 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
2613 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
2614 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
2615 ///
2616 /// Overflow and underflow:
2617 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
2618 /// - If $0<f(x,u,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
2619 /// - If $0<f(x,u,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
2620 /// instead.
2621 /// - If $0<f(x,u,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
2622 /// - If $2^{-2^{30}-1}<f(x,u,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
2623 /// instead.
2624 /// - If $-2^{-2^{30}}<f(x,u,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
2625 /// - If $-2^{-2^{30}}<f(x,u,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
2626 /// instead.
2627 /// - If $-2^{-2^{30}-1}\leq f(x,u,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
2628 /// - If $-2^{-2^{30}}<f(x,u,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
2629 /// returned instead.
2630 ///
2631 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
2632 /// which takes more than $2^{30}$ bits of precision.
2633 ///
2634 /// If you want to specify an output precision, consider using
2635 /// [`Float::cos_with_period_prec_round`] instead. If you know you'll be using the `Nearest`
2636 /// rounding mode, consider using [`Float::cos_with_period_prec`] with the input's precision
2637 /// instead.
2638 ///
2639 /// # Worst-case complexity
2640 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
2641 ///
2642 /// $M(n, e) = O((n+e) \log (n+e))$
2643 ///
2644 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
2645 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the argument is
2646 /// reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is then taken at a working
2647 /// precision of about $n + e$ bits, which needs $\pi$ to that many bits.
2648 ///
2649 /// # Panics
2650 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
2651 /// precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or $x$ is zero or
2652 /// not finite, or $u$ is zero).
2653 ///
2654 /// # Examples
2655 /// ```
2656 /// use malachite_base::rounding_modes::RoundingMode::*;
2657 /// use malachite_float::Float;
2658 /// use std::cmp::Ordering::*;
2659 ///
2660 /// let (c, o) = Float::from_unsigned_prec(1u32, 10)
2661 /// .0
2662 /// .cos_with_period_round(7, Floor);
2663 /// assert_eq!(c.to_string(), "0.62305");
2664 /// assert_eq!(o, Less);
2665 ///
2666 /// let (c, o) = Float::from_unsigned_prec(1u32, 10)
2667 /// .0
2668 /// .cos_with_period_round(7, Ceiling);
2669 /// assert_eq!(c.to_string(), "0.62402");
2670 /// assert_eq!(o, Greater);
2671 ///
2672 /// let (c, o) = Float::from_unsigned_prec(1u32, 10)
2673 /// .0
2674 /// .cos_with_period_round(7, Nearest);
2675 /// assert_eq!(c.to_string(), "0.62305");
2676 /// assert_eq!(o, Less);
2677 /// ```
2678 #[inline]
2679 pub fn cos_with_period_round(self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
2680 let prec = self.significant_bits();
2681 self.cos_with_period_prec_round(u, prec, rm)
2682 }
2683
2684 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2685 /// the result with the specified rounding mode. The [`Float`] is taken by reference. An
2686 /// [`Ordering`] is also returned, indicating whether the rounded cosine is less than, equal to,
2687 /// or greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`],
2688 /// whenever this function returns a `NaN` it also returns `Equal`.
2689 ///
2690 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
2691 /// description of the possible rounding modes.
2692 ///
2693 /// $$
2694 /// f(x,u,m) = \cos(2\pi x/u)+\varepsilon.
2695 /// $$
2696 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2697 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
2698 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$, where $p$ is the precision of the input.
2699 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
2700 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$, where $p$ is the precision of the input.
2701 ///
2702 /// If the output has a precision, it is the precision of the input.
2703 ///
2704 /// Special cases:
2705 /// - $f(\text{NaN},u,m)=\text{NaN}$
2706 /// - $f(\pm\infty,u,m)=\text{NaN}$
2707 /// - $f(x,0,m)=\text{NaN}$
2708 /// - $f(\pm0.0,u,m)=1.0$
2709 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
2710 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
2711 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
2712 /// $-1/2$.
2713 ///
2714 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
2715 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
2716 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
2717 ///
2718 /// Overflow and underflow:
2719 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
2720 /// - If $0<f(x,u,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
2721 /// - If $0<f(x,u,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
2722 /// instead.
2723 /// - If $0<f(x,u,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
2724 /// - If $2^{-2^{30}-1}<f(x,u,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
2725 /// instead.
2726 /// - If $-2^{-2^{30}}<f(x,u,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
2727 /// - If $-2^{-2^{30}}<f(x,u,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
2728 /// instead.
2729 /// - If $-2^{-2^{30}-1}\leq f(x,u,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
2730 /// - If $-2^{-2^{30}}<f(x,u,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
2731 /// returned instead.
2732 ///
2733 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
2734 /// which takes more than $2^{30}$ bits of precision.
2735 ///
2736 /// If you want to specify an output precision, consider using
2737 /// [`Float::cos_with_period_prec_round_ref`] instead. If you know you'll be using the `Nearest`
2738 /// rounding mode, consider using [`Float::cos_with_period_prec_ref`] with the input's precision
2739 /// instead.
2740 ///
2741 /// # Worst-case complexity
2742 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
2743 ///
2744 /// $M(n, e) = O((n+e) \log (n+e))$
2745 ///
2746 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
2747 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the argument is
2748 /// reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is then taken at a working
2749 /// precision of about $n + e$ bits, which needs $\pi$ to that many bits.
2750 ///
2751 /// # Panics
2752 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
2753 /// precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or $x$ is zero or
2754 /// not finite, or $u$ is zero).
2755 ///
2756 /// # Examples
2757 /// ```
2758 /// use malachite_base::rounding_modes::RoundingMode::*;
2759 /// use malachite_float::Float;
2760 /// use std::cmp::Ordering::*;
2761 ///
2762 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 10).0).cos_with_period_round_ref(7, Floor);
2763 /// assert_eq!(c.to_string(), "0.62305");
2764 /// assert_eq!(o, Less);
2765 ///
2766 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 10).0).cos_with_period_round_ref(7, Ceiling);
2767 /// assert_eq!(c.to_string(), "0.62402");
2768 /// assert_eq!(o, Greater);
2769 ///
2770 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 10).0).cos_with_period_round_ref(7, Nearest);
2771 /// assert_eq!(c.to_string(), "0.62305");
2772 /// assert_eq!(o, Less);
2773 /// ```
2774 #[inline]
2775 pub fn cos_with_period_round_ref(&self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
2776 self.cos_with_period_prec_round_ref(u, self.significant_bits(), rm)
2777 }
2778
2779 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn (so that
2780 /// `u = 360` is degrees), rounding the result to the precision of the input and to the nearest
2781 /// [`Float`]. The [`Float`] is taken by value.
2782 ///
2783 /// If the cosine is equidistant from two [`Float`]s with the precision of the input, the
2784 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2785 /// description of the `Nearest` rounding mode.
2786 ///
2787 /// See [`Float::cos_with_period_prec_round`] for the error bounds, the special and closed-form
2788 /// cases, overflow and underflow, and the complexity; this function behaves the same way with
2789 /// `prec` equal to the precision of the input and `rm` equal to `Nearest`.
2790 ///
2791 /// If you want to use a rounding mode other than `Nearest`, consider using
2792 /// [`Float::cos_with_period_round`] instead. If you want to specify an output precision,
2793 /// consider using [`Float::cos_with_period_prec`]. If you want both of these things, consider
2794 /// using [`Float::cos_with_period_prec_round`].
2795 ///
2796 /// # Examples
2797 /// ```
2798 /// use malachite_float::Float;
2799 ///
2800 /// let c = Float::from_unsigned_prec(1u32, 10).0.cos_with_period(7);
2801 /// assert_eq!(c.to_string(), "0.62305");
2802 ///
2803 /// // a half turn is exactly -1
2804 /// assert_eq!(
2805 /// Float::from(180u32).cos_with_period(360).to_string(),
2806 /// "-1.00"
2807 /// );
2808 /// ```
2809 #[inline]
2810 pub fn cos_with_period(self, u: u64) -> Self {
2811 let prec = self.significant_bits();
2812 self.cos_with_period_prec(u, prec).0
2813 }
2814
2815 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn (so that
2816 /// `u = 360` is degrees), rounding the result to the precision of the input and to the nearest
2817 /// [`Float`]. The [`Float`] is taken by reference.
2818 ///
2819 /// If the cosine is equidistant from two [`Float`]s with the precision of the input, the
2820 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2821 /// description of the `Nearest` rounding mode.
2822 ///
2823 /// See [`Float::cos_with_period_prec_round`] for the error bounds, the special and closed-form
2824 /// cases, overflow and underflow, and the complexity; this function behaves the same way with
2825 /// `prec` equal to the precision of the input and `rm` equal to `Nearest`.
2826 ///
2827 /// If you want to use a rounding mode other than `Nearest`, consider using
2828 /// [`Float::cos_with_period_round_ref`] instead. If you want to specify an output precision,
2829 /// consider using [`Float::cos_with_period_prec_ref`]. If you want both of these things,
2830 /// consider using [`Float::cos_with_period_prec_round_ref`].
2831 ///
2832 /// # Examples
2833 /// ```
2834 /// use malachite_float::Float;
2835 ///
2836 /// let c = (&Float::from_unsigned_prec(1u32, 10).0).cos_with_period_ref(7);
2837 /// assert_eq!(c.to_string(), "0.62305");
2838 /// ```
2839 #[inline]
2840 pub fn cos_with_period_ref(&self, u: u64) -> Self {
2841 self.cos_with_period_prec_ref(u, self.significant_bits()).0
2842 }
2843
2844 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2845 /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
2846 /// replaced by the result, and an [`Ordering`] is returned, indicating whether the rounded
2847 /// cosine is less than, equal to, or greater than the exact cosine. Although `NaN`s are not
2848 /// comparable to any [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
2849 ///
2850 /// See [`RoundingMode`] for a description of the possible rounding modes.
2851 ///
2852 /// $$
2853 /// x \gets \cos(2\pi x/u)+\varepsilon.
2854 /// $$
2855 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2856 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
2857 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$.
2858 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
2859 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$.
2860 ///
2861 /// If the output has a precision, it is `prec`.
2862 ///
2863 /// See the [`Float::cos_with_period_prec_round`] documentation for information on special
2864 /// cases, overflow, and underflow.
2865 ///
2866 /// If you know you'll be using `Nearest`, consider using [`Float::cos_with_period_prec_assign`]
2867 /// instead. If you know that your target precision is the precision of the input, consider
2868 /// using [`Float::cos_with_period_round_assign`] instead.
2869 ///
2870 /// # Worst-case complexity
2871 /// $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))$
2872 ///
2873 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
2874 ///
2875 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
2876 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
2877 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
2878 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
2879 /// bits.
2880 ///
2881 /// # Panics
2882 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2883 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or
2884 /// $x$ is zero or not finite, or $u$ is zero).
2885 ///
2886 /// # Examples
2887 /// ```
2888 /// use malachite_base::rounding_modes::RoundingMode::*;
2889 /// use malachite_float::Float;
2890 /// use std::cmp::Ordering::*;
2891 ///
2892 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
2893 /// assert_eq!(x.cos_with_period_prec_round_assign(7, 10, Floor), Less);
2894 /// assert_eq!(x.to_string(), "0.62305");
2895 ///
2896 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
2897 /// assert_eq!(x.cos_with_period_prec_round_assign(7, 10, Ceiling), Greater);
2898 /// assert_eq!(x.to_string(), "0.62402");
2899 ///
2900 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
2901 /// assert_eq!(x.cos_with_period_prec_round_assign(7, 10, Nearest), Less);
2902 /// assert_eq!(x.to_string(), "0.62305");
2903 /// ```
2904 #[inline]
2905 pub fn cos_with_period_prec_round_assign(
2906 &mut self,
2907 u: u64,
2908 prec: u64,
2909 rm: RoundingMode,
2910 ) -> Ordering {
2911 let o;
2912 (*self, o) = self.cos_with_period_prec_round_ref(u, prec, rm);
2913 o
2914 }
2915
2916 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2917 /// the result to the nearest value of the specified precision. The [`Float`] is replaced by the
2918 /// result, and an [`Ordering`] is returned, indicating whether the rounded cosine is less than,
2919 /// equal to, or greater than the exact cosine. Although `NaN`s are not comparable to any
2920 /// [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
2921 ///
2922 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
2923 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
2924 /// the `Nearest` rounding mode.
2925 ///
2926 /// $$
2927 /// x \gets \cos(2\pi x/u)+\varepsilon.
2928 /// $$
2929 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2930 /// - If $x$ is finite and $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi
2931 /// x/u)|\rfloor-p}$.
2932 ///
2933 /// If the output has a precision, it is `prec`.
2934 ///
2935 /// See the [`Float::cos_with_period_prec`] documentation for information on special cases,
2936 /// overflow, and underflow.
2937 ///
2938 /// If you want to use a rounding mode other than `Nearest`, consider using
2939 /// [`Float::cos_with_period_prec_round_assign`] instead. If you know that your target precision
2940 /// is the precision of the input, consider using [`Float::cos_with_period_round_assign`] with
2941 /// `Nearest` instead.
2942 ///
2943 /// # Worst-case complexity
2944 /// $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))$
2945 ///
2946 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
2947 ///
2948 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
2949 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
2950 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
2951 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
2952 /// bits.
2953 ///
2954 /// # Panics
2955 /// Panics if `prec` is zero.
2956 ///
2957 /// # Examples
2958 /// ```
2959 /// use malachite_float::Float;
2960 /// use std::cmp::Ordering::*;
2961 ///
2962 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
2963 /// assert_eq!(x.cos_with_period_prec_assign(7, 10), Less);
2964 /// assert_eq!(x.to_string(), "0.62305");
2965 ///
2966 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
2967 /// assert_eq!(x.cos_with_period_prec_assign(8, 10), Less);
2968 /// assert_eq!(x.to_string(), "0.70703");
2969 /// ```
2970 #[inline]
2971 pub fn cos_with_period_prec_assign(&mut self, u: u64, prec: u64) -> Ordering {
2972 self.cos_with_period_prec_round_assign(u, prec, Nearest)
2973 }
2974
2975 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn, rounding
2976 /// the result with the specified rounding mode. The [`Float`] is replaced by the result, and an
2977 /// [`Ordering`] is returned, indicating whether the rounded cosine is less than, equal to, or
2978 /// greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever
2979 /// this function sets a `NaN` it also returns `Equal`.
2980 ///
2981 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
2982 /// description of the possible rounding modes.
2983 ///
2984 /// $$
2985 /// x \gets \cos(2\pi x/u)+\varepsilon.
2986 /// $$
2987 /// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
2988 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
2989 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p+1}$, where $p$ is the precision of the input.
2990 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
2991 /// 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$, where $p$ is the precision of the input.
2992 ///
2993 /// If the output has a precision, it is the precision of the input.
2994 ///
2995 /// See the [`Float::cos_with_period_round`] documentation for information on special cases,
2996 /// overflow, and underflow.
2997 ///
2998 /// If you want to specify an output precision, consider using
2999 /// [`Float::cos_with_period_prec_round_assign`] instead. If you know you'll be using the
3000 /// `Nearest` rounding mode, consider using [`Float::cos_with_period_prec_assign`] with the
3001 /// input's precision instead.
3002 ///
3003 /// # Worst-case complexity
3004 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
3005 ///
3006 /// $M(n, e) = O((n+e) \log (n+e))$
3007 ///
3008 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
3009 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the argument is
3010 /// reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is then taken at a working
3011 /// precision of about $n + e$ bits, which needs $\pi$ to that many bits.
3012 ///
3013 /// # Panics
3014 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
3015 /// precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or $x$ is zero or
3016 /// not finite, or $u$ is zero).
3017 ///
3018 /// # Examples
3019 /// ```
3020 /// use malachite_base::rounding_modes::RoundingMode::*;
3021 /// use malachite_float::Float;
3022 /// use std::cmp::Ordering::*;
3023 ///
3024 /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
3025 /// assert_eq!(x.cos_with_period_round_assign(7, Floor), Less);
3026 /// assert_eq!(x.to_string(), "0.62305");
3027 ///
3028 /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
3029 /// assert_eq!(x.cos_with_period_round_assign(7, Ceiling), Greater);
3030 /// assert_eq!(x.to_string(), "0.62402");
3031 ///
3032 /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
3033 /// assert_eq!(x.cos_with_period_round_assign(7, Nearest), Less);
3034 /// assert_eq!(x.to_string(), "0.62305");
3035 /// ```
3036 #[inline]
3037 pub fn cos_with_period_round_assign(&mut self, u: u64, rm: RoundingMode) -> Ordering {
3038 let prec = self.significant_bits();
3039 self.cos_with_period_prec_round_assign(u, prec, rm)
3040 }
3041
3042 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Float`] measured in $u$ths of a turn (so that
3043 /// `u = 360` is degrees), rounding the result to the precision of the input and to the nearest
3044 /// [`Float`]. The [`Float`] is replaced by the result.
3045 ///
3046 /// If the cosine is equidistant from two [`Float`]s with the precision of the input, the
3047 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3048 /// description of the `Nearest` rounding mode.
3049 ///
3050 /// See [`Float::cos_with_period_prec_round`] for the error bounds, the special and closed-form
3051 /// cases, overflow and underflow, and the complexity; this function behaves the same way with
3052 /// `prec` equal to the precision of the input and `rm` equal to `Nearest`.
3053 ///
3054 /// If you want to use a rounding mode other than `Nearest`, consider using
3055 /// [`Float::cos_with_period_round_assign`] instead. If you want to specify an output precision,
3056 /// consider using [`Float::cos_with_period_prec_assign`]. If you want both of these things,
3057 /// consider using [`Float::cos_with_period_prec_round_assign`].
3058 ///
3059 /// # Examples
3060 /// ```
3061 /// use malachite_float::Float;
3062 ///
3063 /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
3064 /// x.cos_with_period_assign(7);
3065 /// assert_eq!(x.to_string(), "0.62305");
3066 /// ```
3067 #[inline]
3068 pub fn cos_with_period_assign(&mut self, u: u64) {
3069 let prec = self.significant_bits();
3070 self.cos_with_period_prec_assign(u, prec);
3071 }
3072}
3073
3074// Computes cos(2 pi q) for a nonzero fraction of a turn q with |q| < 1, rounded to precision `prec`
3075// with rounding mode `rm`. This is the `Rational` counterpart of
3076// `cos_with_period_prec_round_normal_ref`, with the same structure: the small-input shortcut, the
3077// closed-form cases, and a Ziv loop around the cosine of a `Float` approximation of 2 pi q, whose
3078// three roundings (q, pi, and the product) give the same error bound as MPFR's cosu. `rm` may be
3079// `Exact` only in the exact cases.
3080pub(crate) fn cos_turns_helper(q: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
3081 let exp_q = q.floor_log_base_2_abs() + 1;
3082 // for q small, we have |cos(2*pi*q)-1| < 1/2*(2*pi*q)^2 < 2^5*q^2 < 2^(5 + 2 EXP(q))
3083 let err = -(exp_q << 1) - 5;
3084 if err > 0 {
3085 let err = u64::exact_from(err);
3086 if err > prec + 1 {
3087 // As in the `Float` version: the reference value 1 always rounds, the bound need not
3088 // exceed prec + 2, and such a tiny q is neither a special case nor exact.
3089 assert_ne!(rm, Exact, "Inexact cos_with_period");
3090 return float_round_near_x(&Float::ONE, min(err, prec + 2), false, prec, rm).unwrap();
3091 }
3092 }
3093 // The special cases need |q| >= 1/12
3094 if exp_q >= -4
3095 && let Some(result) = cos_turns_special_case(q, prec, rm)
3096 {
3097 return result;
3098 }
3099 // Only the exact cases can be rounded exactly
3100 assert_ne!(rm, Exact, "Inexact cos_with_period");
3101 let mut w = prec + prec.ceiling_log_base_2() + 8;
3102 let mut increment = Limb::WIDTH;
3103 loop {
3104 // t = 2*pi*q * (1 + theta)^3 where |theta| <= 2^-w, from rounding q, pi, and the product
3105 let mut t = Float::pi_prec(w).0 << 1u32;
3106 t.mul_prec_assign(Float::from_rational_prec_ref(q, w).0, w);
3107 if t == 0u32 {
3108 // Unreachable in practice: such a q is caught by the small-input shortcut above unless
3109 // `prec` exceeds 2^31 bits.
3110 fail_on_untested_path("cos_turns_helper, 2 pi q underflowed");
3111 return match rm {
3112 Floor | Down => (one_neighbor(prec, false), Less),
3113 _ => (Float::one_prec(prec), Greater),
3114 };
3115 }
3116 // since w >= 2, |(1 + theta)^3 - 1| <= 4*theta <= 2^(2-w), and |cos(t) - cos(2 pi q)| <=
3117 // |s| <= 2^(EXP(t) + 2 - w)
3118 let exp_t = i64::from(t.get_exponent().unwrap());
3119 let w_i = i64::exact_from(w);
3120 let mut err = exp_t + 2 - w_i;
3121 t.cos_prec_assign(w);
3122 let exp_t = t.get_exponent().map_or(Float::MIN_EXPONENT_I64, i64::from);
3123 if exp_t < 0 {
3124 let cancel = u64::exact_from(-exp_t);
3125 if cancel >= max(NEAR_ZERO_MIN_CANCEL, prec >> 4)
3126 && let Some(result) = trig_turns_near_zero(q, prec, rm, true)
3127 {
3128 return result;
3129 }
3130 }
3131 // the total error is at most 2^err + ulp(t)/2, bounded by 2^(EXP(t)-w) if err <= EXP(t)-w-1
3132 // and by 2^(err+1) otherwise; then normalized for can_round
3133 err = if err < exp_t - w_i {
3134 exp_t - w_i
3135 } else {
3136 err + 1
3137 };
3138 err = exp_t - err;
3139 if err > 0 && float_can_round(t.significand_ref().unwrap(), u64::exact_from(err), prec, rm)
3140 {
3141 return Float::from_float_prec_round(t, prec, rm);
3142 }
3143 w += increment;
3144 increment = w >> 1;
3145 }
3146}
3147
3148impl Float {
3149 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Rational`] measured in $u$ths of a turn,
3150 /// rounding the result to the specified precision and with the specified rounding mode, and
3151 /// returning the result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is
3152 /// also returned, indicating whether the rounded cosine is less than, equal to, or greater than
3153 /// the exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this
3154 /// function returns a `NaN` it also returns `Equal`.
3155 ///
3156 /// See [`RoundingMode`] for a description of the possible rounding modes.
3157 ///
3158 /// $$
3159 /// f(x,u,p,m) = \cos(2\pi x/u)+\varepsilon.
3160 /// $$
3161 /// - If $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
3162 /// - If $u\neq 0$ and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi
3163 /// x/u)|\rfloor-p+1}$.
3164 /// - If $u\neq 0$ and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos(2\pi
3165 /// x/u)|\rfloor-p}$.
3166 ///
3167 /// If the output has a precision, it is `prec`.
3168 ///
3169 /// Special cases:
3170 /// - $f(x,0,p,m)=\text{NaN}$
3171 /// - $f(0,u,p,m)=1$
3172 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
3173 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
3174 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
3175 /// $-1/2$.
3176 ///
3177 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
3178 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
3179 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
3180 ///
3181 /// Overflow and underflow:
3182 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
3183 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
3184 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
3185 /// instead.
3186 /// - If $0<f(x,u,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
3187 /// - If $2^{-2^{30}-1}<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
3188 /// instead.
3189 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
3190 /// instead.
3191 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
3192 /// instead.
3193 /// - If $-2^{-2^{30}-1}\leq f(x,u,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
3194 /// - If $-2^{-2^{30}}<f(x,u,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
3195 /// returned instead.
3196 ///
3197 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
3198 /// which takes a denominator of more than $2^{30}$ bits.
3199 ///
3200 /// If you know you'll be using `Nearest`, consider using
3201 /// [`Float::cos_with_period_rational_prec`] instead.
3202 ///
3203 /// # Worst-case complexity
3204 /// $T(n, m) = O(n (\log n)^3 \log\log n + (n+m) (\log (n+m))^2 \log\log (n+m))$
3205 ///
3206 /// $M(n, m) = O((n+m) \log (n+m))$
3207 ///
3208 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
3209 /// `x.significant_bits()`: the fraction of a turn is reduced modulo 1 exactly, so only its size
3210 /// and the precision drive the cost, not the magnitude of $x$.
3211 ///
3212 /// # Panics
3213 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
3214 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or
3215 /// $x$ or $u$ is zero).
3216 ///
3217 /// # Examples
3218 /// ```
3219 /// use malachite_base::num::basic::traits::One;
3220 /// use malachite_base::rounding_modes::RoundingMode::*;
3221 /// use malachite_float::Float;
3222 /// use malachite_q::Rational;
3223 /// use std::cmp::Ordering::*;
3224 ///
3225 /// let (c, o) = Float::cos_with_period_rational_prec_round(Rational::ONE, 7, 10, Floor);
3226 /// assert_eq!(c.to_string(), "0.62305");
3227 /// assert_eq!(o, Less);
3228 ///
3229 /// let (c, o) = Float::cos_with_period_rational_prec_round(Rational::ONE, 7, 10, Ceiling);
3230 /// assert_eq!(c.to_string(), "0.62402");
3231 /// assert_eq!(o, Greater);
3232 ///
3233 /// let (c, o) = Float::cos_with_period_rational_prec_round(Rational::ONE, 7, 10, Nearest);
3234 /// assert_eq!(c.to_string(), "0.62305");
3235 /// assert_eq!(o, Less);
3236 ///
3237 /// // a third of a turn is exact
3238 /// let (c, o) = Float::cos_with_period_rational_prec_round(
3239 /// Rational::from_unsigneds(1u8, 3),
3240 /// 1,
3241 /// 10,
3242 /// Exact,
3243 /// );
3244 /// assert_eq!(c.to_string(), "-0.50000");
3245 /// assert_eq!(o, Equal);
3246 /// ```
3247 #[inline]
3248 #[allow(clippy::needless_pass_by_value)]
3249 pub fn cos_with_period_rational_prec_round(
3250 x: Rational,
3251 u: u64,
3252 prec: u64,
3253 rm: RoundingMode,
3254 ) -> (Self, Ordering) {
3255 Self::cos_with_period_rational_prec_round_ref(&x, u, prec, rm)
3256 }
3257
3258 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Rational`] measured in $u$ths of a turn,
3259 /// rounding the result to the specified precision and with the specified rounding mode, and
3260 /// returning the result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`]
3261 /// is also returned, indicating whether the rounded cosine is less than, equal to, or greater
3262 /// than the exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this
3263 /// function returns a `NaN` it also returns `Equal`.
3264 ///
3265 /// See [`RoundingMode`] for a description of the possible rounding modes.
3266 ///
3267 /// $$
3268 /// f(x,u,p,m) = \cos(2\pi x/u)+\varepsilon.
3269 /// $$
3270 /// - If $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
3271 /// - If $u\neq 0$ and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi
3272 /// x/u)|\rfloor-p+1}$.
3273 /// - If $u\neq 0$ and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\cos(2\pi
3274 /// x/u)|\rfloor-p}$.
3275 ///
3276 /// If the output has a precision, it is `prec`.
3277 ///
3278 /// Special cases:
3279 /// - $f(x,0,p,m)=\text{NaN}$
3280 /// - $f(0,u,p,m)=1$
3281 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
3282 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
3283 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
3284 /// $-1/2$.
3285 ///
3286 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
3287 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
3288 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
3289 ///
3290 /// Overflow and underflow:
3291 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
3292 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
3293 /// - If $0<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
3294 /// instead.
3295 /// - If $0<f(x,u,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
3296 /// - If $2^{-2^{30}-1}<f(x,u,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
3297 /// instead.
3298 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
3299 /// instead.
3300 /// - If $-2^{-2^{30}}<f(x,u,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
3301 /// instead.
3302 /// - If $-2^{-2^{30}-1}\leq f(x,u,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
3303 /// - If $-2^{-2^{30}}<f(x,u,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
3304 /// returned instead.
3305 ///
3306 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
3307 /// which takes a denominator of more than $2^{30}$ bits.
3308 ///
3309 /// If you know you'll be using `Nearest`, consider using
3310 /// [`Float::cos_with_period_rational_prec_ref`] instead.
3311 ///
3312 /// # Worst-case complexity
3313 /// $T(n, m) = O(n (\log n)^3 \log\log n + (n+m) (\log (n+m))^2 \log\log (n+m))$
3314 ///
3315 /// $M(n, m) = O((n+m) \log (n+m))$
3316 ///
3317 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
3318 /// `x.significant_bits()`: the fraction of a turn is reduced modulo 1 exactly, so only its size
3319 /// and the precision drive the cost, not the magnitude of $x$.
3320 ///
3321 /// # Panics
3322 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
3323 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/4$ or $1/6$, or
3324 /// $x$ or $u$ is zero).
3325 ///
3326 /// # Examples
3327 /// ```
3328 /// use malachite_base::num::basic::traits::One;
3329 /// use malachite_base::rounding_modes::RoundingMode::*;
3330 /// use malachite_float::Float;
3331 /// use malachite_q::Rational;
3332 /// use std::cmp::Ordering::*;
3333 ///
3334 /// let (c, o) = Float::cos_with_period_rational_prec_round_ref(&Rational::ONE, 7, 10, Floor);
3335 /// assert_eq!(c.to_string(), "0.62305");
3336 /// assert_eq!(o, Less);
3337 ///
3338 /// let (c, o) = Float::cos_with_period_rational_prec_round_ref(&Rational::ONE, 7, 10, Ceiling);
3339 /// assert_eq!(c.to_string(), "0.62402");
3340 /// assert_eq!(o, Greater);
3341 ///
3342 /// let (c, o) = Float::cos_with_period_rational_prec_round_ref(&Rational::ONE, 7, 10, Nearest);
3343 /// assert_eq!(c.to_string(), "0.62305");
3344 /// assert_eq!(o, Less);
3345 ///
3346 /// // a third of a turn is exact
3347 /// let (c, o) = Float::cos_with_period_rational_prec_round_ref(
3348 /// &Rational::from_unsigneds(1u8, 3),
3349 /// 1,
3350 /// 10,
3351 /// Exact,
3352 /// );
3353 /// assert_eq!(c.to_string(), "-0.50000");
3354 /// assert_eq!(o, Equal);
3355 /// ```
3356 pub fn cos_with_period_rational_prec_round_ref(
3357 x: &Rational,
3358 u: u64,
3359 prec: u64,
3360 rm: RoundingMode,
3361 ) -> (Self, Ordering) {
3362 assert_ne!(prec, 0);
3363 // for u = 0, return NaN
3364 if u == 0 {
3365 return (Self::NAN, Equal);
3366 }
3367 // cos(0) = 1
3368 if *x == 0u32 {
3369 return (Self::one_prec(prec), Equal);
3370 }
3371 // q = x/u, reduced to [-1/2, 1/2]: cos(2 pi q) has period 1 in q, and an input just below a
3372 // multiple of the period must land near 0, not near 1, for the small-input shortcut to
3373 // apply (otherwise the working precision would have to grow to the whole cancellation in 1
3374 // - cos)
3375 let q = x / Rational::from(u);
3376 let whole = Rational::from(Integer::rounding_from(&q, Nearest).0);
3377 let q = q - whole;
3378 if q == 0u32 {
3379 return (Self::one_prec(prec), Equal);
3380 }
3381 cos_turns_helper(&q, prec, rm)
3382 }
3383
3384 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Rational`] measured in $u$ths of a turn,
3385 /// rounding the result to the nearest value of the specified precision, and returning the
3386 /// result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned,
3387 /// indicating whether the rounded cosine is less than, equal to, or greater than the exact
3388 /// cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
3389 /// a `NaN` it also returns `Equal`.
3390 ///
3391 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
3392 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
3393 /// the `Nearest` rounding mode.
3394 ///
3395 /// $$
3396 /// f(x,u,p) = \cos(2\pi x/u)+\varepsilon.
3397 /// $$
3398 /// - If $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
3399 /// - If $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$.
3400 ///
3401 /// If the output has a precision, it is `prec`.
3402 ///
3403 /// Special cases:
3404 /// - $f(x,0,p)=\text{NaN}$
3405 /// - $f(0,u,p)=1$
3406 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
3407 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
3408 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
3409 /// $-1/2$.
3410 ///
3411 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
3412 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
3413 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
3414 ///
3415 /// Overflow and underflow:
3416 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
3417 /// - If $0<f(x,u,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
3418 /// - If $2^{-2^{30}-1}<f(x,u,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
3419 /// - If $-2^{-2^{30}-1}\leq f(x,u,p)<0$, $-0.0$ is returned instead.
3420 /// - If $-2^{-2^{30}}<f(x,u,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
3421 ///
3422 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
3423 /// which takes a denominator of more than $2^{30}$ bits.
3424 ///
3425 /// If you want to use a rounding mode other than `Nearest`, consider using
3426 /// [`Float::cos_with_period_rational_prec_round`] instead.
3427 ///
3428 /// # Worst-case complexity
3429 /// $T(n, m) = O(n (\log n)^3 \log\log n + (n+m) (\log (n+m))^2 \log\log (n+m))$
3430 ///
3431 /// $M(n, m) = O((n+m) \log (n+m))$
3432 ///
3433 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
3434 /// `x.significant_bits()`: the fraction of a turn is reduced modulo 1 exactly, so only its size
3435 /// and the precision drive the cost, not the magnitude of $x$.
3436 ///
3437 /// # Panics
3438 /// Panics if `prec` is zero.
3439 ///
3440 /// # Examples
3441 /// ```
3442 /// use malachite_base::num::basic::traits::One;
3443 /// use malachite_float::Float;
3444 /// use malachite_q::Rational;
3445 /// use std::cmp::Ordering::*;
3446 ///
3447 /// let (c, o) = Float::cos_with_period_rational_prec(Rational::ONE, 7, 10);
3448 /// assert_eq!(c.to_string(), "0.62305");
3449 /// assert_eq!(o, Less);
3450 ///
3451 /// let (c, o) = Float::cos_with_period_rational_prec(Rational::ONE, 7, 53);
3452 /// assert_eq!(c.to_string(), "0.62348980185873348");
3453 /// assert_eq!(o, Less);
3454 ///
3455 /// // an eighth of a turn: sqrt(2)/2
3456 /// let (c, o) = Float::cos_with_period_rational_prec(Rational::from_unsigneds(1u8, 8), 1, 53);
3457 /// assert_eq!(c.to_string(), "0.70710678118654757");
3458 /// assert_eq!(o, Greater);
3459 /// ```
3460 #[inline]
3461 #[allow(clippy::needless_pass_by_value)]
3462 pub fn cos_with_period_rational_prec(x: Rational, u: u64, prec: u64) -> (Self, Ordering) {
3463 Self::cos_with_period_rational_prec_round_ref(&x, u, prec, Nearest)
3464 }
3465
3466 /// Computes $\cos(2\pi x/u)$, the cosine of a [`Rational`] measured in $u$ths of a turn,
3467 /// rounding the result to the nearest value of the specified precision, and returning the
3468 /// result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also
3469 /// returned, indicating whether the rounded cosine is less than, equal to, or greater than the
3470 /// exact cosine. Although `NaN`s are not comparable to any [`Float`], whenever this function
3471 /// returns a `NaN` it also returns `Equal`.
3472 ///
3473 /// If the cosine is equidistant from two [`Float`]s with the specified precision, the [`Float`]
3474 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
3475 /// the `Nearest` rounding mode.
3476 ///
3477 /// $$
3478 /// f(x,u,p) = \cos(2\pi x/u)+\varepsilon.
3479 /// $$
3480 /// - If $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
3481 /// - If $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$.
3482 ///
3483 /// If the output has a precision, it is `prec`.
3484 ///
3485 /// Special cases:
3486 /// - $f(x,0,p)=\text{NaN}$
3487 /// - $f(0,u,p)=1$
3488 /// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd
3489 /// multiple of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's
3490 /// `cosPi`); and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or
3491 /// $-1/2$.
3492 ///
3493 /// When $x/u$ in lowest terms has denominator 5, 8, 10, or 12, the result is $\pm\varphi/2$,
3494 /// $\pm(\varphi-1)/2$, $\pm\sqrt2/2$, or $\pm\sqrt3/2$, and is computed from a single correctly
3495 /// rounded constant rather than from $\pi$ and a cosine, which is far faster.
3496 ///
3497 /// Overflow and underflow:
3498 /// - Since $|\cos(2\pi x/u)|\leq 1$, the result never overflows.
3499 /// - If $0<f(x,u,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
3500 /// - If $2^{-2^{30}-1}<f(x,u,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
3501 /// - If $-2^{-2^{30}-1}\leq f(x,u,p)<0$, $-0.0$ is returned instead.
3502 /// - If $-2^{-2^{30}}<f(x,u,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
3503 ///
3504 /// Underflow requires $x/u$ within $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one,
3505 /// which takes a denominator of more than $2^{30}$ bits.
3506 ///
3507 /// If you want to use a rounding mode other than `Nearest`, consider using
3508 /// [`Float::cos_with_period_rational_prec_round_ref`] instead.
3509 ///
3510 /// # Worst-case complexity
3511 /// $T(n, m) = O(n (\log n)^3 \log\log n + (n+m) (\log (n+m))^2 \log\log (n+m))$
3512 ///
3513 /// $M(n, m) = O((n+m) \log (n+m))$
3514 ///
3515 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
3516 /// `x.significant_bits()`: the fraction of a turn is reduced modulo 1 exactly, so only its size
3517 /// and the precision drive the cost, not the magnitude of $x$.
3518 ///
3519 /// # Panics
3520 /// Panics if `prec` is zero.
3521 ///
3522 /// # Examples
3523 /// ```
3524 /// use malachite_base::num::basic::traits::One;
3525 /// use malachite_float::Float;
3526 /// use malachite_q::Rational;
3527 /// use std::cmp::Ordering::*;
3528 ///
3529 /// let (c, o) = Float::cos_with_period_rational_prec_ref(&Rational::ONE, 7, 10);
3530 /// assert_eq!(c.to_string(), "0.62305");
3531 /// assert_eq!(o, Less);
3532 ///
3533 /// let (c, o) = Float::cos_with_period_rational_prec_ref(&Rational::ONE, 7, 53);
3534 /// assert_eq!(c.to_string(), "0.62348980185873348");
3535 /// assert_eq!(o, Less);
3536 ///
3537 /// // an eighth of a turn: sqrt(2)/2
3538 /// let (c, o) =
3539 /// Float::cos_with_period_rational_prec_ref(&Rational::from_unsigneds(1u8, 8), 1, 53);
3540 /// assert_eq!(c.to_string(), "0.70710678118654757");
3541 /// assert_eq!(o, Greater);
3542 /// ```
3543 #[inline]
3544 pub fn cos_with_period_rational_prec_ref(x: &Rational, u: u64, prec: u64) -> (Self, Ordering) {
3545 Self::cos_with_period_rational_prec_round_ref(x, u, prec, Nearest)
3546 }
3547}
3548
3549impl Float {
3550 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3551 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
3552 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded cosine is
3553 /// less than, equal to, or greater than the exact cosine. Although `NaN`s are not comparable to
3554 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
3555 ///
3556 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_prec_round`] for
3557 /// the error bounds, the special and closed-form cases (integers give $\pm1$, half-integers
3558 /// give $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms),
3559 /// overflow and underflow, and the complexity, with $u = 2$.
3560 ///
3561 /// # Panics
3562 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
3563 /// with the given precision.
3564 ///
3565 /// # Examples
3566 /// ```
3567 /// use malachite_base::num::basic::traits::One;
3568 /// use malachite_base::rounding_modes::RoundingMode::*;
3569 /// use malachite_float::Float;
3570 /// use std::cmp::Ordering::*;
3571 ///
3572 /// let (c, o) = Float::from(0.1f64).cos_pi_prec_round(10, Floor);
3573 /// assert_eq!(c.to_string(), "0.95020");
3574 /// assert_eq!(o, Less);
3575 ///
3576 /// let (c, o) = Float::from(0.1f64).cos_pi_prec_round(10, Ceiling);
3577 /// assert_eq!(c.to_string(), "0.95117");
3578 /// assert_eq!(o, Greater);
3579 ///
3580 /// // a half-turn is exactly -1
3581 /// let (c, o) = Float::ONE.cos_pi_prec_round(10, Exact);
3582 /// assert_eq!(c.to_string(), "-1.0000");
3583 /// assert_eq!(o, Equal);
3584 /// ```
3585 #[inline]
3586 pub fn cos_pi_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
3587 self.cos_with_period_prec_round(2, prec, rm)
3588 }
3589
3590 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3591 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
3592 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded cosine
3593 /// is less than, equal to, or greater than the exact cosine. Although `NaN`s are not comparable
3594 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
3595 ///
3596 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_prec_round_ref`]
3597 /// for the error bounds, the special and closed-form cases (integers give $\pm1$, half-integers
3598 /// give $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms),
3599 /// overflow and underflow, and the complexity, with $u = 2$.
3600 ///
3601 /// # Panics
3602 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
3603 /// with the given precision.
3604 ///
3605 /// # Examples
3606 /// ```
3607 /// use malachite_base::num::basic::traits::One;
3608 /// use malachite_base::rounding_modes::RoundingMode::*;
3609 /// use malachite_float::Float;
3610 /// use std::cmp::Ordering::*;
3611 ///
3612 /// let (c, o) = (Float::from(0.1f64)).cos_pi_prec_round_ref(10, Floor);
3613 /// assert_eq!(c.to_string(), "0.95020");
3614 /// assert_eq!(o, Less);
3615 ///
3616 /// let (c, o) = (Float::from(0.1f64)).cos_pi_prec_round_ref(10, Ceiling);
3617 /// assert_eq!(c.to_string(), "0.95117");
3618 /// assert_eq!(o, Greater);
3619 ///
3620 /// // a half-turn is exactly -1
3621 /// let (c, o) = (&Float::ONE).cos_pi_prec_round_ref(10, Exact);
3622 /// assert_eq!(c.to_string(), "-1.0000");
3623 /// assert_eq!(o, Equal);
3624 /// ```
3625 #[inline]
3626 pub fn cos_pi_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
3627 self.cos_with_period_prec_round_ref(2, prec, rm)
3628 }
3629
3630 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3631 /// result to the nearest value of the specified precision. The [`Float`] is taken by value. An
3632 /// [`Ordering`] is also returned, indicating whether the rounded cosine is less than, equal to,
3633 /// or greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`],
3634 /// whenever this function returns a `NaN` it also returns `Equal`.
3635 ///
3636 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_prec`] for the
3637 /// error bounds, the special and closed-form cases (integers give $\pm1$, half-integers give
3638 /// $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms), overflow
3639 /// and underflow, and the complexity, with $u = 2$.
3640 ///
3641 /// # Panics
3642 /// Panics if `prec` is zero.
3643 ///
3644 /// # Examples
3645 /// ```
3646 /// use malachite_float::Float;
3647 /// use std::cmp::Ordering::*;
3648 ///
3649 /// let (c, o) = Float::from(0.1f64).cos_pi_prec(10);
3650 /// assert_eq!(c.to_string(), "0.95117");
3651 /// assert_eq!(o, Greater);
3652 ///
3653 /// let (c, o) = Float::from(0.1f64).cos_pi_prec(53);
3654 /// assert_eq!(c.to_string(), "0.95105651629515353");
3655 /// assert_eq!(o, Less);
3656 /// ```
3657 #[inline]
3658 pub fn cos_pi_prec(self, prec: u64) -> (Self, Ordering) {
3659 self.cos_with_period_prec(2, prec)
3660 }
3661
3662 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3663 /// result to the nearest value of the specified precision. The [`Float`] is taken by reference.
3664 /// An [`Ordering`] is also returned, indicating whether the rounded cosine is less than, equal
3665 /// to, or greater than the exact cosine. Although `NaN`s are not comparable to any [`Float`],
3666 /// whenever this function returns a `NaN` it also returns `Equal`.
3667 ///
3668 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_prec_ref`] for
3669 /// the error bounds, the special and closed-form cases (integers give $\pm1$, half-integers
3670 /// give $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms),
3671 /// overflow and underflow, and the complexity, with $u = 2$.
3672 ///
3673 /// # Panics
3674 /// Panics if `prec` is zero.
3675 ///
3676 /// # Examples
3677 /// ```
3678 /// use malachite_float::Float;
3679 /// use std::cmp::Ordering::*;
3680 ///
3681 /// let (c, o) = (Float::from(0.1f64)).cos_pi_prec_ref(10);
3682 /// assert_eq!(c.to_string(), "0.95117");
3683 /// assert_eq!(o, Greater);
3684 ///
3685 /// let (c, o) = (Float::from(0.1f64)).cos_pi_prec_ref(53);
3686 /// assert_eq!(c.to_string(), "0.95105651629515353");
3687 /// assert_eq!(o, Less);
3688 /// ```
3689 #[inline]
3690 pub fn cos_pi_prec_ref(&self, prec: u64) -> (Self, Ordering) {
3691 self.cos_with_period_prec_ref(2, prec)
3692 }
3693
3694 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3695 /// result with the specified rounding mode. The precision of the output is the precision of the
3696 /// input. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether
3697 /// the rounded cosine is less than, equal to, or greater than the exact cosine. Although `NaN`s
3698 /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
3699 /// `Equal`.
3700 ///
3701 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_round`] for the
3702 /// error bounds, the special and closed-form cases (integers give $\pm1$, half-integers give
3703 /// $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms), overflow
3704 /// and underflow, and the complexity, with $u = 2$.
3705 ///
3706 /// # Panics
3707 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
3708 /// precision.
3709 ///
3710 /// # Examples
3711 /// ```
3712 /// use malachite_base::rounding_modes::RoundingMode::*;
3713 /// use malachite_float::Float;
3714 /// use std::cmp::Ordering::*;
3715 ///
3716 /// let (c, o) = Float::from(0.1f64).cos_pi_round(Floor);
3717 /// assert_eq!(c.to_string(), "0.95105651629515342");
3718 /// assert_eq!(o, Less);
3719 ///
3720 /// let (c, o) = Float::from(0.1f64).cos_pi_round(Nearest);
3721 /// assert_eq!(c.to_string(), "0.95105651629515364");
3722 /// assert_eq!(o, Greater);
3723 /// ```
3724 #[inline]
3725 pub fn cos_pi_round(self, rm: RoundingMode) -> (Self, Ordering) {
3726 self.cos_with_period_round(2, rm)
3727 }
3728
3729 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3730 /// result with the specified rounding mode. The precision of the output is the precision of the
3731 /// input. The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating
3732 /// whether the rounded cosine is less than, equal to, or greater than the exact cosine.
3733 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
3734 /// it also returns `Equal`.
3735 ///
3736 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_round_ref`] for
3737 /// the error bounds, the special and closed-form cases (integers give $\pm1$, half-integers
3738 /// give $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms),
3739 /// overflow and underflow, and the complexity, with $u = 2$.
3740 ///
3741 /// # Panics
3742 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
3743 /// precision.
3744 ///
3745 /// # Examples
3746 /// ```
3747 /// use malachite_base::rounding_modes::RoundingMode::*;
3748 /// use malachite_float::Float;
3749 /// use std::cmp::Ordering::*;
3750 ///
3751 /// let (c, o) = (Float::from(0.1f64)).cos_pi_round_ref(Floor);
3752 /// assert_eq!(c.to_string(), "0.95105651629515342");
3753 /// assert_eq!(o, Less);
3754 ///
3755 /// let (c, o) = (Float::from(0.1f64)).cos_pi_round_ref(Nearest);
3756 /// assert_eq!(c.to_string(), "0.95105651629515364");
3757 /// assert_eq!(o, Greater);
3758 /// ```
3759 #[inline]
3760 pub fn cos_pi_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
3761 self.cos_with_period_round_ref(2, rm)
3762 }
3763
3764 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3765 /// result to the precision of the input and to the nearest [`Float`]. The [`Float`] is taken by
3766 /// value.
3767 ///
3768 /// If the cosine is equidistant from two [`Float`]s with the precision of the input, the
3769 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3770 /// description of the `Nearest` rounding mode.
3771 ///
3772 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period`] for the error
3773 /// bounds, the special and closed-form cases (integers give $\pm1$, half-integers give $+0.0$,
3774 /// and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms), overflow and
3775 /// underflow, and the complexity, with $u = 2$.
3776 ///
3777 /// If you want to use a rounding mode other than `Nearest`, consider using
3778 /// [`Float::cos_pi_round`] instead. If you want to specify an output precision, consider using
3779 /// [`Float::cos_pi_prec`]. If you want both of these things, consider using
3780 /// [`Float::cos_pi_prec_round`].
3781 ///
3782 /// # Examples
3783 /// ```
3784 /// use malachite_float::Float;
3785 ///
3786 /// let c = Float::from(0.1f64).cos_pi();
3787 /// assert_eq!(c.to_string(), "0.95105651629515364");
3788 ///
3789 /// // an integer is exactly 1 or -1
3790 /// assert_eq!(Float::from(3u32).cos_pi().to_string(), "-1.0");
3791 /// ```
3792 #[inline]
3793 pub fn cos_pi(self) -> Self {
3794 let prec = self.significant_bits();
3795 self.cos_pi_prec(prec).0
3796 }
3797
3798 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3799 /// result to the precision of the input and to the nearest [`Float`]. The [`Float`] is taken by
3800 /// reference.
3801 ///
3802 /// If the cosine is equidistant from two [`Float`]s with the precision of the input, the
3803 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3804 /// description of the `Nearest` rounding mode.
3805 ///
3806 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period`] for the error
3807 /// bounds, the special and closed-form cases (integers give $\pm1$, half-integers give $+0.0$,
3808 /// and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms), overflow and
3809 /// underflow, and the complexity, with $u = 2$.
3810 ///
3811 /// If you want to use a rounding mode other than `Nearest`, consider using
3812 /// [`Float::cos_pi_round_ref`] instead. If you want to specify an output precision, consider
3813 /// using [`Float::cos_pi_prec_ref`]. If you want both of these things, consider using
3814 /// [`Float::cos_pi_prec_round_ref`].
3815 ///
3816 /// # Examples
3817 /// ```
3818 /// use malachite_float::Float;
3819 ///
3820 /// let c = (&Float::from(0.1f64)).cos_pi_ref();
3821 /// assert_eq!(c.to_string(), "0.95105651629515364");
3822 /// ```
3823 #[inline]
3824 pub fn cos_pi_ref(&self) -> Self {
3825 self.cos_pi_prec_ref(self.significant_bits()).0
3826 }
3827
3828 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3829 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
3830 /// replaced by the result, and an [`Ordering`] is returned, indicating whether the rounded
3831 /// cosine is less than, equal to, or greater than the exact cosine. Although `NaN`s are not
3832 /// comparable to any [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
3833 ///
3834 /// This is `cos_with_period` with a period of 2: see
3835 /// [`Float::cos_with_period_prec_round_assign`] for the error bounds, the special and
3836 /// closed-form cases (integers give $\pm1$, half-integers give $+0.0$, and multiples of $1/3$,
3837 /// $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms), overflow and underflow, and the
3838 /// complexity, with $u = 2$.
3839 ///
3840 /// # Panics
3841 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
3842 /// with the given precision.
3843 ///
3844 /// # Examples
3845 /// ```
3846 /// use malachite_base::rounding_modes::RoundingMode::*;
3847 /// use malachite_float::Float;
3848 /// use std::cmp::Ordering::*;
3849 ///
3850 /// let mut x = Float::from(0.1f64);
3851 /// assert_eq!(x.cos_pi_prec_round_assign(10, Floor), Less);
3852 /// assert_eq!(x.to_string(), "0.95020");
3853 ///
3854 /// let mut x = Float::from(0.1f64);
3855 /// assert_eq!(x.cos_pi_prec_round_assign(10, Ceiling), Greater);
3856 /// assert_eq!(x.to_string(), "0.95117");
3857 /// ```
3858 #[inline]
3859 pub fn cos_pi_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
3860 self.cos_with_period_prec_round_assign(2, prec, rm)
3861 }
3862
3863 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3864 /// result to the nearest value of the specified precision. The [`Float`] is replaced by the
3865 /// result, and an [`Ordering`] is returned, indicating whether the rounded cosine is less than,
3866 /// equal to, or greater than the exact cosine. Although `NaN`s are not comparable to any
3867 /// [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
3868 ///
3869 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_prec_assign`] for
3870 /// the error bounds, the special and closed-form cases (integers give $\pm1$, half-integers
3871 /// give $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms),
3872 /// overflow and underflow, and the complexity, with $u = 2$.
3873 ///
3874 /// # Panics
3875 /// Panics if `prec` is zero.
3876 ///
3877 /// # Examples
3878 /// ```
3879 /// use malachite_float::Float;
3880 /// use std::cmp::Ordering::*;
3881 ///
3882 /// let mut x = Float::from(0.1f64);
3883 /// assert_eq!(x.cos_pi_prec_assign(10), Greater);
3884 /// assert_eq!(x.to_string(), "0.95117");
3885 /// ```
3886 #[inline]
3887 pub fn cos_pi_prec_assign(&mut self, prec: u64) -> Ordering {
3888 self.cos_with_period_prec_assign(2, prec)
3889 }
3890
3891 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3892 /// result with the specified rounding mode. The precision of the output is the precision of the
3893 /// input. The [`Float`] is replaced by the result, and an [`Ordering`] is returned, indicating
3894 /// whether the rounded cosine is less than, equal to, or greater than the exact cosine.
3895 /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it
3896 /// also returns `Equal`.
3897 ///
3898 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period_round_assign`]
3899 /// for the error bounds, the special and closed-form cases (integers give $\pm1$, half-integers
3900 /// give $+0.0$, and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms),
3901 /// overflow and underflow, and the complexity, with $u = 2$.
3902 ///
3903 /// # Panics
3904 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
3905 /// precision.
3906 ///
3907 /// # Examples
3908 /// ```
3909 /// use malachite_base::rounding_modes::RoundingMode::*;
3910 /// use malachite_float::Float;
3911 /// use std::cmp::Ordering::*;
3912 ///
3913 /// let mut x = Float::from(0.1f64);
3914 /// assert_eq!(x.cos_pi_round_assign(Floor), Less);
3915 /// assert_eq!(x.to_string(), "0.95105651629515342");
3916 /// ```
3917 #[inline]
3918 pub fn cos_pi_round_assign(&mut self, rm: RoundingMode) -> Ordering {
3919 self.cos_with_period_round_assign(2, rm)
3920 }
3921
3922 /// Computes $\cos(\pi x)$, the cosine of a [`Float`] measured in half-turns, rounding the
3923 /// result to the precision of the input and to the nearest [`Float`]. The [`Float`] is replaced
3924 /// by the result.
3925 ///
3926 /// If the cosine is equidistant from two [`Float`]s with the precision of the input, the
3927 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
3928 /// description of the `Nearest` rounding mode.
3929 ///
3930 /// This is `cos_with_period` with a period of 2: see [`Float::cos_with_period`] for the error
3931 /// bounds, the special and closed-form cases (integers give $\pm1$, half-integers give $+0.0$,
3932 /// and multiples of $1/3$, $1/4$, $1/5$, $1/6$, and $1/10$ have closed forms), overflow and
3933 /// underflow, and the complexity, with $u = 2$.
3934 ///
3935 /// If you want to use a rounding mode other than `Nearest`, consider using
3936 /// [`Float::cos_pi_round_assign`] instead. If you want to specify an output precision, consider
3937 /// using [`Float::cos_pi_prec_assign`]. If you want both of these things, consider using
3938 /// [`Float::cos_pi_prec_round_assign`].
3939 ///
3940 /// # Examples
3941 /// ```
3942 /// use malachite_float::Float;
3943 ///
3944 /// let mut x = Float::from(0.1f64);
3945 /// x.cos_pi_assign();
3946 /// assert_eq!(x.to_string(), "0.95105651629515364");
3947 /// ```
3948 #[inline]
3949 pub fn cos_pi_assign(&mut self) {
3950 let prec = self.significant_bits();
3951 self.cos_pi_prec_assign(prec);
3952 }
3953
3954 /// Computes $\cos(\pi x)$, the cosine of a [`Rational`] measured in half-turns, rounding the
3955 /// result to the specified precision and with the specified rounding mode and returning the
3956 /// result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned,
3957 /// indicating whether the rounded cosine is less than, equal to, or greater than the exact
3958 /// cosine.
3959 ///
3960 /// This is `cos_with_period_rational` with a period of 2: see
3961 /// [`Float::cos_with_period_rational_prec_round`] for the error bounds, the special and
3962 /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
3963 ///
3964 /// # Panics
3965 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
3966 /// with the given precision.
3967 ///
3968 /// # Examples
3969 /// ```
3970 /// use malachite_base::rounding_modes::RoundingMode::*;
3971 /// use malachite_float::Float;
3972 /// use malachite_q::Rational;
3973 /// use std::cmp::Ordering::*;
3974 ///
3975 /// let (c, o) = Float::cos_pi_rational_prec_round(Rational::from_unsigneds(1u8, 7), 10, Floor);
3976 /// assert_eq!(c.to_string(), "0.90039");
3977 /// assert_eq!(o, Less);
3978 ///
3979 /// // a third of a half-turn is exactly 1/2
3980 /// let (c, o) = Float::cos_pi_rational_prec_round(Rational::from_unsigneds(1u8, 3), 10, Exact);
3981 /// assert_eq!(c.to_string(), "0.50000");
3982 /// assert_eq!(o, Equal);
3983 /// ```
3984 #[inline]
3985 #[allow(clippy::needless_pass_by_value)]
3986 pub fn cos_pi_rational_prec_round(
3987 x: Rational,
3988 prec: u64,
3989 rm: RoundingMode,
3990 ) -> (Self, Ordering) {
3991 Self::cos_with_period_rational_prec_round_ref(&x, 2, prec, rm)
3992 }
3993
3994 /// Computes $\cos(\pi x)$, the cosine of a [`Rational`] measured in half-turns, rounding the
3995 /// result to the specified precision and with the specified rounding mode and returning the
3996 /// result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also
3997 /// returned, indicating whether the rounded cosine is less than, equal to, or greater than the
3998 /// exact cosine.
3999 ///
4000 /// This is `cos_with_period_rational` with a period of 2: see
4001 /// [`Float::cos_with_period_rational_prec_round_ref`] for the error bounds, the special and
4002 /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
4003 ///
4004 /// # Panics
4005 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
4006 /// with the given precision.
4007 ///
4008 /// # Examples
4009 /// ```
4010 /// use malachite_base::rounding_modes::RoundingMode::*;
4011 /// use malachite_float::Float;
4012 /// use malachite_q::Rational;
4013 /// use std::cmp::Ordering::*;
4014 ///
4015 /// let (c, o) =
4016 /// Float::cos_pi_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 7), 10, Ceiling);
4017 /// assert_eq!(c.to_string(), "0.90137");
4018 /// assert_eq!(o, Greater);
4019 /// ```
4020 #[inline]
4021 pub fn cos_pi_rational_prec_round_ref(
4022 x: &Rational,
4023 prec: u64,
4024 rm: RoundingMode,
4025 ) -> (Self, Ordering) {
4026 Self::cos_with_period_rational_prec_round_ref(x, 2, prec, rm)
4027 }
4028
4029 /// Computes $\cos(\pi x)$, the cosine of a [`Rational`] measured in half-turns, rounding the
4030 /// result to the nearest value of the specified precision and returning the result as a
4031 /// [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating
4032 /// whether the rounded cosine is less than, equal to, or greater than the exact cosine.
4033 ///
4034 /// This is `cos_with_period_rational` with a period of 2: see
4035 /// [`Float::cos_with_period_rational_prec`] for the error bounds, the special and closed-form
4036 /// cases, overflow and underflow, and the complexity, with $u = 2$.
4037 ///
4038 /// # Panics
4039 /// Panics if `prec` is zero.
4040 ///
4041 /// # Examples
4042 /// ```
4043 /// use malachite_float::Float;
4044 /// use malachite_q::Rational;
4045 /// use std::cmp::Ordering::*;
4046 ///
4047 /// let (c, o) = Float::cos_pi_rational_prec(Rational::from_unsigneds(1u8, 7), 53);
4048 /// assert_eq!(c.to_string(), "0.90096886790241915");
4049 /// assert_eq!(o, Greater);
4050 /// ```
4051 #[inline]
4052 #[allow(clippy::needless_pass_by_value)]
4053 pub fn cos_pi_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
4054 Self::cos_with_period_rational_prec_ref(&x, 2, prec)
4055 }
4056
4057 /// Computes $\cos(\pi x)$, the cosine of a [`Rational`] measured in half-turns, rounding the
4058 /// result to the nearest value of the specified precision and returning the result as a
4059 /// [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also returned,
4060 /// indicating whether the rounded cosine is less than, equal to, or greater than the exact
4061 /// cosine.
4062 ///
4063 /// This is `cos_with_period_rational` with a period of 2: see
4064 /// [`Float::cos_with_period_rational_prec_ref`] for the error bounds, the special and
4065 /// closed-form cases, overflow and underflow, and the complexity, with $u = 2$.
4066 ///
4067 /// # Panics
4068 /// Panics if `prec` is zero.
4069 ///
4070 /// # Examples
4071 /// ```
4072 /// use malachite_float::Float;
4073 /// use malachite_q::Rational;
4074 /// use std::cmp::Ordering::*;
4075 ///
4076 /// let (c, o) = Float::cos_pi_rational_prec_ref(&Rational::from_unsigneds(1u8, 7), 53);
4077 /// assert_eq!(c.to_string(), "0.90096886790241915");
4078 /// assert_eq!(o, Greater);
4079 /// ```
4080 #[inline]
4081 pub fn cos_pi_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
4082 Self::cos_with_period_rational_prec_ref(x, 2, prec)
4083 }
4084}
4085
4086impl Cos for Float {
4087 type Output = Self;
4088
4089 /// Computes $\cos x$, the cosine of a [`Float`], taking it by value.
4090 ///
4091 /// If the output has a precision, it is the precision of the input. If the cosine is
4092 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4093 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4094 /// rounding mode.
4095 ///
4096 /// $$
4097 /// f(x) = \cos x+\varepsilon.
4098 /// $$
4099 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
4100 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, where $p$ is
4101 /// the precision of the input.
4102 ///
4103 /// Special cases:
4104 /// - $f(\text{NaN})=\text{NaN}$
4105 /// - $f(\pm\infty)=\text{NaN}$
4106 /// - $f(\pm0.0)=1.0$
4107 ///
4108 /// See the [`Float::cos_round`] documentation for information on overflow and underflow.
4109 ///
4110 /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::cos_round`]
4111 /// instead. If you want to specify the output precision, consider using [`Float::cos_prec`]. If
4112 /// you want both of these things, consider using [`Float::cos_prec_round`].
4113 ///
4114 /// # Worst-case complexity
4115 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
4116 ///
4117 /// $M(n, e) = O((n+e) \log (n+e))$
4118 ///
4119 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
4120 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
4121 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
4122 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
4123 /// e$ bits. Unlike most functions, `cos` therefore gets slower as the magnitude of its input
4124 /// grows, not just as the precision does.
4125 ///
4126 /// # Examples
4127 /// ```
4128 /// use malachite_base::num::arithmetic::traits::Cos;
4129 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, One, Zero};
4130 /// use malachite_float::Float;
4131 ///
4132 /// assert!(Float::NAN.cos().is_nan());
4133 /// assert!(Float::INFINITY.cos().is_nan());
4134 /// assert!(Float::NEGATIVE_INFINITY.cos().is_nan());
4135 /// assert_eq!(Float::ZERO.cos(), Float::ONE);
4136 /// assert_eq!(
4137 /// Float::from_unsigned_prec(1u32, 100).0.cos().to_string(),
4138 /// "0.54030230586813971740093660744335"
4139 /// );
4140 /// assert_eq!(
4141 /// Float::from_unsigned_prec(100u32, 100).0.cos().to_string(),
4142 /// "0.86231887228768393410193851395099"
4143 /// );
4144 /// ```
4145 #[inline]
4146 fn cos(self) -> Self {
4147 let prec = self.significant_bits();
4148 self.cos_prec_round(prec, Nearest).0
4149 }
4150}
4151
4152impl Cos for &Float {
4153 type Output = Float;
4154
4155 /// Computes $\cos x$, the cosine of a [`Float`], taking it by reference.
4156 ///
4157 /// If the output has a precision, it is the precision of the input. If the cosine is
4158 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4159 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4160 /// rounding mode.
4161 ///
4162 /// $$
4163 /// f(x) = \cos x+\varepsilon.
4164 /// $$
4165 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
4166 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, where $p$ is
4167 /// the precision of the input.
4168 ///
4169 /// Special cases:
4170 /// - $f(\text{NaN})=\text{NaN}$
4171 /// - $f(\pm\infty)=\text{NaN}$
4172 /// - $f(\pm0.0)=1.0$
4173 ///
4174 /// See the [`Float::cos_round`] documentation for information on overflow and underflow.
4175 ///
4176 /// If you want to use a rounding mode other than `Nearest`, consider using
4177 /// [`Float::cos_round_ref`] instead. If you want to specify the output precision, consider
4178 /// using [`Float::cos_prec_ref`]. If you want both of these things, consider using
4179 /// [`Float::cos_prec_round_ref`].
4180 ///
4181 /// # Worst-case complexity
4182 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
4183 ///
4184 /// $M(n, e) = O((n+e) \log (n+e))$
4185 ///
4186 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
4187 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
4188 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
4189 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
4190 /// e$ bits. Unlike most functions, `cos` therefore gets slower as the magnitude of its input
4191 /// grows, not just as the precision does.
4192 ///
4193 /// # Examples
4194 /// ```
4195 /// use malachite_base::num::arithmetic::traits::Cos;
4196 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, One, Zero};
4197 /// use malachite_float::Float;
4198 ///
4199 /// assert!(Float::NAN.cos().is_nan());
4200 /// assert!(Float::INFINITY.cos().is_nan());
4201 /// assert!(Float::NEGATIVE_INFINITY.cos().is_nan());
4202 /// assert_eq!(Float::ZERO.cos(), Float::ONE);
4203 /// assert_eq!(
4204 /// (&Float::from_unsigned_prec(1u32, 100).0).cos().to_string(),
4205 /// "0.54030230586813971740093660744335"
4206 /// );
4207 /// assert_eq!(
4208 /// (&Float::from_unsigned_prec(100u32, 100).0)
4209 /// .cos()
4210 /// .to_string(),
4211 /// "0.86231887228768393410193851395099"
4212 /// );
4213 /// ```
4214 #[inline]
4215 fn cos(self) -> Float {
4216 self.cos_prec_round_ref(self.significant_bits(), Nearest).0
4217 }
4218}
4219
4220impl CosAssign for Float {
4221 /// Computes $\cos x$, the cosine of a [`Float`], in place.
4222 ///
4223 /// If the output has a precision, it is the precision of the input. If the cosine is
4224 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
4225 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
4226 /// rounding mode.
4227 ///
4228 /// $$
4229 /// x \gets \cos x+\varepsilon.
4230 /// $$
4231 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
4232 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, where $p$ is
4233 /// the precision of the input.
4234 ///
4235 /// See the [`Float::cos`] documentation for information on special cases, overflow, and
4236 /// underflow.
4237 ///
4238 /// If you want to use a rounding mode other than `Nearest`, consider using
4239 /// [`Float::cos_round_assign`] instead. If you want to specify the output precision, consider
4240 /// using [`Float::cos_prec_assign`]. If you want both of these things, consider using
4241 /// [`Float::cos_prec_round_assign`].
4242 ///
4243 /// # Worst-case complexity
4244 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
4245 ///
4246 /// $M(n, e) = O((n+e) \log (n+e))$
4247 ///
4248 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
4249 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
4250 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
4251 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
4252 /// e$ bits. Unlike most functions, `cos` therefore gets slower as the magnitude of its input
4253 /// grows, not just as the precision does.
4254 ///
4255 /// # Examples
4256 /// ```
4257 /// use malachite_base::num::arithmetic::traits::CosAssign;
4258 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity, One, Zero};
4259 /// use malachite_float::Float;
4260 ///
4261 /// let mut x = Float::NAN;
4262 /// x.cos_assign();
4263 /// assert!(x.is_nan());
4264 ///
4265 /// let mut x = Float::INFINITY;
4266 /// x.cos_assign();
4267 /// assert!(x.is_nan());
4268 ///
4269 /// let mut x = Float::NEGATIVE_INFINITY;
4270 /// x.cos_assign();
4271 /// assert!(x.is_nan());
4272 ///
4273 /// let mut x = Float::ZERO;
4274 /// x.cos_assign();
4275 /// assert_eq!(x, Float::ONE);
4276 ///
4277 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
4278 /// x.cos_assign();
4279 /// assert_eq!(x.to_string(), "0.54030230586813971740093660744335");
4280 ///
4281 /// let mut x = Float::from_unsigned_prec(100u32, 100).0;
4282 /// x.cos_assign();
4283 /// assert_eq!(x.to_string(), "0.86231887228768393410193851395099");
4284 /// ```
4285 #[inline]
4286 fn cos_assign(&mut self) {
4287 let prec = self.significant_bits();
4288 self.cos_prec_round_assign(prec, Nearest);
4289 }
4290}
4291
4292/// Computes $\cos x$, the cosine of a primitive float. Using this function is more accurate than
4293/// using the default `cos` function or the one provided by `libm`.
4294///
4295/// $$
4296/// f(x) = \cos x+\varepsilon.
4297/// $$
4298/// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
4299/// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, where $p$ is the
4300/// precision of the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
4301///
4302/// Special cases:
4303/// - $f(\text{NaN})=\text{NaN}$
4304/// - $f(\pm\infty)=\text{NaN}$
4305/// - $f(\pm0.0)=1.0$
4306///
4307/// Overflow and underflow are not possible: the result lies in $[-1, 1]$, and no [`f32`] or [`f64`]
4308/// is close enough to an odd multiple of $\pi/2$ for its cosine to be subnormal.
4309///
4310/// # Worst-case complexity
4311/// Constant time and additional memory.
4312///
4313/// # Examples
4314/// ```
4315/// use malachite_base::num::basic::traits::NegativeInfinity;
4316/// use malachite_base::num::float::NiceFloat;
4317/// use malachite_float::float::arithmetic::cos::primitive_float_cos;
4318///
4319/// assert!(primitive_float_cos(f32::NAN).is_nan());
4320/// assert!(primitive_float_cos(f32::INFINITY).is_nan());
4321/// assert!(primitive_float_cos(f32::NEGATIVE_INFINITY).is_nan());
4322/// assert_eq!(NiceFloat(primitive_float_cos(0.0f32)), NiceFloat(1.0));
4323/// assert_eq!(NiceFloat(primitive_float_cos(1.0f32)), NiceFloat(0.5403023));
4324/// assert_eq!(
4325/// NiceFloat(primitive_float_cos(1.0f64)),
4326/// NiceFloat(0.5403023058681398)
4327/// );
4328/// ```
4329#[inline]
4330#[allow(clippy::type_repetition_in_bounds)]
4331pub fn primitive_float_cos<T: PrimitiveFloat>(x: T) -> T
4332where
4333 Float: From<T> + PartialOrd<T>,
4334 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
4335{
4336 emulate_float_to_float_fn(Float::cos_prec, x)
4337}
4338
4339/// Computes $\cos x$, the cosine of a [`Rational`], returning the result as a primitive float.
4340///
4341/// $$
4342/// f(x) = \cos x+\varepsilon,
4343/// $$
4344/// where $|\varepsilon| < 2^{\lfloor\log_2 |\cos x|\rfloor-p}$, and $p$ is the precision of the
4345/// output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
4346///
4347/// Special cases:
4348/// - $f(0)=1$
4349///
4350/// Overflow and underflow are not possible: the result lies in $[-1, 1]$, and a [`Rational`] close
4351/// enough to an odd multiple of $\pi/2$ for its cosine to be subnormal would need a denominator of
4352/// more than 100 bits, in which case the result is still correctly rounded.
4353///
4354/// # Worst-case complexity
4355/// $T(m, e) = O((m+e) (\log (m+e))^2 \log\log (m+e))$
4356///
4357/// $M(m, e) = O((m+e) \log (m+e))$
4358///
4359/// where $T$ is time, $M$ is additional memory, $m$ is `x.significant_bits()`, and $e$ is
4360/// `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): for $|x| \geq 4$ the
4361/// argument is reduced modulo $2\pi$, which needs $\pi$ to about $e$ bits.
4362///
4363/// # Examples
4364/// ```
4365/// use malachite_base::num::basic::traits::Zero;
4366/// use malachite_base::num::float::NiceFloat;
4367/// use malachite_float::float::arithmetic::cos::primitive_float_cos_rational;
4368/// use malachite_q::Rational;
4369///
4370/// assert_eq!(
4371/// NiceFloat(primitive_float_cos_rational::<f64>(&Rational::ZERO)),
4372/// NiceFloat(1.0)
4373/// );
4374/// assert_eq!(
4375/// NiceFloat(primitive_float_cos_rational::<f64>(
4376/// &Rational::from_unsigneds(1u8, 3)
4377/// )),
4378/// NiceFloat(0.9449569463147377)
4379/// );
4380/// assert_eq!(
4381/// NiceFloat(primitive_float_cos_rational::<f32>(
4382/// &Rational::from_unsigneds(1u8, 3)
4383/// )),
4384/// NiceFloat(0.94495696)
4385/// );
4386/// assert_eq!(
4387/// NiceFloat(primitive_float_cos_rational::<f64>(&Rational::from(10000))),
4388/// NiceFloat(-0.9521553682590148)
4389/// );
4390/// ```
4391#[inline]
4392#[allow(clippy::type_repetition_in_bounds)]
4393pub fn primitive_float_cos_rational<T: PrimitiveFloat>(x: &Rational) -> T
4394where
4395 Float: PartialOrd<T>,
4396 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
4397{
4398 emulate_rational_to_float_fn(Float::cos_rational_prec_ref, x)
4399}
4400
4401/// Computes $\cos(2\pi x/u)$, the cosine of a primitive float measured in $u$ths of a turn (so that
4402/// `u = 360` is degrees).
4403///
4404/// $$
4405/// f(x,u) = \cos(2\pi x/u)+\varepsilon.
4406/// $$
4407/// - If $x$ is not finite or $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
4408/// - If $x$ is finite and $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi
4409/// x/u)|\rfloor-p}$, where $p$ is the precision of the output (24 if `T` is a [`f32`] and 53 if
4410/// `T` is a [`f64`]).
4411///
4412/// Special cases:
4413/// - $f(\text{NaN},u)=\text{NaN}$
4414/// - $f(\pm\infty,u)=\text{NaN}$
4415/// - $f(x,0)=\text{NaN}$
4416/// - $f(\pm0.0,u)=1.0$
4417/// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd multiple
4418/// of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's `cosPi`);
4419/// and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or $-1/2$.
4420///
4421/// Overflow and underflow are not possible: the result lies in $[-1, 1]$, and no [`f32`] or [`f64`]
4422/// is close enough to an odd quarter turn, without being one, for its cosine to be subnormal.
4423///
4424/// # Worst-case complexity
4425/// Constant time and additional memory.
4426///
4427/// # Examples
4428/// ```
4429/// use malachite_base::num::float::NiceFloat;
4430/// use malachite_float::float::arithmetic::cos::primitive_float_cos_with_period;
4431///
4432/// assert!(primitive_float_cos_with_period(f32::NAN, 360).is_nan());
4433/// assert!(primitive_float_cos_with_period(f32::INFINITY, 360).is_nan());
4434/// assert!(primitive_float_cos_with_period(1.0f32, 0).is_nan());
4435/// assert_eq!(
4436/// NiceFloat(primitive_float_cos_with_period(0.0f32, 360)),
4437/// NiceFloat(1.0)
4438/// );
4439/// assert_eq!(
4440/// NiceFloat(primitive_float_cos_with_period(90.0f32, 360)),
4441/// NiceFloat(0.0)
4442/// );
4443/// assert_eq!(
4444/// NiceFloat(primitive_float_cos_with_period(60.0f64, 360)),
4445/// NiceFloat(0.5)
4446/// );
4447/// assert_eq!(
4448/// NiceFloat(primitive_float_cos_with_period(1.0f32, 7)),
4449/// NiceFloat(0.6234898)
4450/// );
4451/// assert_eq!(
4452/// NiceFloat(primitive_float_cos_with_period(1.0f64, 7)),
4453/// NiceFloat(0.6234898018587335)
4454/// );
4455/// ```
4456#[inline]
4457#[allow(clippy::type_repetition_in_bounds)]
4458pub fn primitive_float_cos_with_period<T: PrimitiveFloat>(x: T, u: u64) -> T
4459where
4460 Float: From<T> + PartialOrd<T>,
4461 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
4462{
4463 emulate_float_to_float_fn(|x, prec| Float::cos_with_period_prec(x, u, prec), x)
4464}
4465
4466/// Computes $\cos(2\pi x/u)$, the cosine of a [`Rational`] measured in $u$ths of a turn (so that `u
4467/// = 360` is degrees), returning the result as a primitive float.
4468///
4469/// $$
4470/// f(x,u) = \cos(2\pi x/u)+\varepsilon.
4471/// $$
4472/// - If $u=0$, $\varepsilon$ may be ignored or assumed to be 0.
4473/// - If $u\neq 0$, then $|\varepsilon| < 2^{\lfloor\log_2 |\cos(2\pi x/u)|\rfloor-p}$, where $p$ is
4474/// the precision of the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
4475///
4476/// Special cases:
4477/// - $f(x,0)=\text{NaN}$
4478/// - $f(0,u)=1$
4479/// - If $x/u$ is a multiple of $1/2$, the result is exactly $1$ or $-1$; if it is an odd multiple
4480/// of $1/4$, the result is exactly $0.0$ (always positive, following IEEE 754-2019's `cosPi`);
4481/// and if it is an odd multiple of $1/6$ or $1/3$, the result is exactly $1/2$ or $-1/2$.
4482///
4483/// Overflow and underflow are not possible: the result lies in $[-1, 1]$, and a [`Rational`] close
4484/// enough to an odd quarter turn, without being one, for its cosine to be subnormal would need a
4485/// denominator of more than 100 bits, in which case the result is still correctly rounded.
4486///
4487/// # Worst-case complexity
4488/// $T(m) = O(m (\log m)^2 \log\log m)$
4489///
4490/// $M(m) = O(m \log m)$
4491///
4492/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`: the fraction of
4493/// a turn is reduced modulo 1 exactly, so the magnitude of $x$ does not drive the cost.
4494///
4495/// # Examples
4496/// ```
4497/// use malachite_base::num::basic::traits::Zero;
4498/// use malachite_base::num::float::NiceFloat;
4499/// use malachite_float::float::arithmetic::cos::primitive_float_cos_with_period_rational;
4500/// use malachite_q::Rational;
4501///
4502/// assert!(primitive_float_cos_with_period_rational::<f64>(&Rational::ZERO, 0).is_nan());
4503/// assert_eq!(
4504/// NiceFloat(primitive_float_cos_with_period_rational::<f64>(
4505/// &Rational::ZERO,
4506/// 360
4507/// )),
4508/// NiceFloat(1.0)
4509/// );
4510/// // a third of a turn is exactly -1/2
4511/// assert_eq!(
4512/// NiceFloat(primitive_float_cos_with_period_rational::<f64>(
4513/// &Rational::from_unsigneds(1u8, 3),
4514/// 1
4515/// )),
4516/// NiceFloat(-0.5)
4517/// );
4518/// assert_eq!(
4519/// NiceFloat(primitive_float_cos_with_period_rational::<f32>(
4520/// &Rational::from_unsigneds(1u8, 7),
4521/// 1
4522/// )),
4523/// NiceFloat(0.6234898)
4524/// );
4525/// assert_eq!(
4526/// NiceFloat(primitive_float_cos_with_period_rational::<f64>(
4527/// &Rational::from_unsigneds(1u8, 7),
4528/// 1
4529/// )),
4530/// NiceFloat(0.6234898018587335)
4531/// );
4532/// ```
4533#[inline]
4534#[allow(clippy::type_repetition_in_bounds)]
4535pub fn primitive_float_cos_with_period_rational<T: PrimitiveFloat>(x: &Rational, u: u64) -> T
4536where
4537 Float: PartialOrd<T>,
4538 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
4539{
4540 emulate_rational_to_float_fn(
4541 |x, prec| Float::cos_with_period_rational_prec_ref(x, u, prec),
4542 x,
4543 )
4544}
4545
4546/// Computes $\cos(\pi x)$, the cosine of a primitive float measured in half-turns.
4547///
4548/// This is `primitive_float_cos_with_period` with a period of 2: see
4549/// [`primitive_float_cos_with_period`] for the error bound and the special cases, with $u = 2$.
4550/// Half-integers give exactly $+0.0$ and integers exactly $\pm1$.
4551///
4552/// # Worst-case complexity
4553/// Constant time and additional memory.
4554///
4555/// # Examples
4556/// ```
4557/// use malachite_base::num::float::NiceFloat;
4558/// use malachite_float::float::arithmetic::cos::primitive_float_cos_pi;
4559///
4560/// assert!(primitive_float_cos_pi(f32::NAN).is_nan());
4561/// assert_eq!(NiceFloat(primitive_float_cos_pi(0.5f32)), NiceFloat(0.0));
4562/// assert_eq!(NiceFloat(primitive_float_cos_pi(1.0f64)), NiceFloat(-1.0));
4563/// assert_eq!(
4564/// NiceFloat(primitive_float_cos_pi(0.1f32)),
4565/// NiceFloat(0.95105654)
4566/// );
4567/// assert_eq!(
4568/// NiceFloat(primitive_float_cos_pi(0.1f64)),
4569/// NiceFloat(0.9510565162951535)
4570/// );
4571/// ```
4572#[inline]
4573#[allow(clippy::type_repetition_in_bounds)]
4574pub fn primitive_float_cos_pi<T: PrimitiveFloat>(x: T) -> T
4575where
4576 Float: From<T> + PartialOrd<T>,
4577 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
4578{
4579 primitive_float_cos_with_period(x, 2)
4580}
4581
4582/// Computes $\cos(\pi x)$, the cosine of a [`Rational`] measured in half-turns, returning the
4583/// result as a primitive float.
4584///
4585/// This is `primitive_float_cos_with_period_rational` with a period of 2: see
4586/// [`primitive_float_cos_with_period_rational`] for the error bound, the special cases, and the
4587/// complexity, with $u = 2$.
4588///
4589/// # Worst-case complexity
4590/// $T(m) = O(m (\log m)^2 \log\log m)$
4591///
4592/// $M(m) = O(m \log m)$
4593///
4594/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`.
4595///
4596/// # Examples
4597/// ```
4598/// use malachite_base::num::float::NiceFloat;
4599/// use malachite_float::float::arithmetic::cos::primitive_float_cos_pi_rational;
4600/// use malachite_q::Rational;
4601///
4602/// // a third of a half-turn is exactly 1/2
4603/// assert_eq!(
4604/// NiceFloat(primitive_float_cos_pi_rational::<f64>(
4605/// &Rational::from_unsigneds(1u8, 3)
4606/// )),
4607/// NiceFloat(0.5)
4608/// );
4609/// assert_eq!(
4610/// NiceFloat(primitive_float_cos_pi_rational::<f64>(
4611/// &Rational::from_unsigneds(1u8, 7)
4612/// )),
4613/// NiceFloat(0.9009688679024191)
4614/// );
4615/// ```
4616#[inline]
4617#[allow(clippy::type_repetition_in_bounds)]
4618pub fn primitive_float_cos_pi_rational<T: PrimitiveFloat>(x: &Rational) -> T
4619where
4620 Float: PartialOrd<T>,
4621 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
4622{
4623 primitive_float_cos_with_period_rational(x, 2)
4624}