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