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