malachite_float/float/arithmetic/sec.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5// Copyright © 2005-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 secant. `mpfr_sec` (`sec.c`) instantiates the generic reciprocal template
16// (`gen_inverse.h`) with the cosine: the cosine is taken at the working precision, rounded toward
17// zero, its reciprocal is rounded to nearest, and the result is certified with two bits of slack,
18// inside a Ziv loop. The secant never underflows, since its magnitude is at least 1, but it
19// overflows for an input within 2^(-2^30) of an odd multiple of pi/2, which MPFR's wider exponent
20// range never sees; a reciprocal at the top of the range is decided from an exact bracket instead.
21
22use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
23use crate::float::arithmetic::cos::{
24 cos_rational_helper, cos_turns_helper, phi_minus_1_prec_round, signed_constant,
25};
26use crate::float::arithmetic::round_near_x::{float_round_near_x, round_from_below};
27use crate::float::arithmetic::tan::reciprocal_ziv_loop;
28use crate::{Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
29use core::cmp::Ordering::{self, Equal};
30use core::cmp::{max, min};
31use malachite_base::num::arithmetic::traits::{CeilingLogBase2, Mod, Sec, SecAssign};
32use malachite_base::num::basic::floats::PrimitiveFloat;
33use malachite_base::num::basic::integers::PrimitiveInt;
34use malachite_base::num::basic::traits::{Infinity as InfinityTrait, NaN as NaNTrait, One};
35use malachite_base::num::comparison::traits::PartialOrdAbs;
36use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
37use malachite_base::num::logic::traits::SignificantBits;
38use malachite_base::rounding_modes::RoundingMode::{self, *};
39use malachite_nz::integer::Integer;
40use malachite_q::Rational;
41
42// This is mpfr_sec from sec.c, MPFR 4.2.2, with the bracket path for results near the top of the
43// exponent range.
44fn sec_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
45 assert_ne!(rm, Exact, "Inexact sec");
46 let exp_x = i64::from(x.get_exponent().unwrap());
47 // sec(x) = 1 + x^2/2 + ..., more precisely |sec(x) - 1| < x^2 for |x| <= 1, so the error is
48 // below 2^(2*EXP(x)) and lies above 1.
49 //
50 // MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, __gmpfr_one, -2 * MPFR_GET_EXP (x), 0, 1, r, ...)
51 let neg_err = -(exp_x << 1);
52 if neg_err > 0 {
53 let err = u64::exact_from(neg_err);
54 if err > prec + 1 {
55 // The reference value 1 has precision 1 < err, so float_round_near_x always succeeds.
56 // The error bound only has to clear prec + 1; passing an enormous err (a tiny x has one
57 // around 2^31) would make float_round_near_x do work proportional to it.
58 return float_round_near_x(&Float::ONE, min(err, prec + 2), true, prec, rm).unwrap();
59 }
60 }
61 reciprocal_ziv_loop(prec, rm, |m| x.cos_prec_round_ref(m, Down).0)
62}
63
64// Computes sec(x) for a nonzero `Rational` x, rounded to precision `prec` with rounding mode `rm`.
65// (sec(0) = 1 is handled by the caller.) The secant of a nonzero rational is transcendental, so the
66// result is never exactly representable and `rm` must not be `Exact`.
67//
68// This is the `Float` algorithm with the cosine taken from `cos_rational_helper`, which rounds the
69// input once and handles both a tiny x and an x too large to be a `Float`, and with a direct
70// bracket for a tiny input, where sec x is 1 + x^2/2 + O(x^4).
71pub(crate) fn sec_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
72 assert_ne!(rm, Exact, "Inexact sec");
73 let exp_x = x.floor_log_base_2_abs() + 1; // the MPFR-style exponent of x
74 // sec(x) = 1 + x^2/2 + 5x^4/24 + ..., with every term positive, and for |x| <= 1/2 the terms
75 // past x^2/2 sum to less than x^4, so [1 + x^2/2, 1 + x^2/2 + x^4] brackets the secant. x^2 <
76 // 2^(-prec - 1) here, so the secant lies strictly between 1 and 1 + 2^(-prec - 1), short of the
77 // next `Float` above 1 and of the midpoint below it: the answer is 1 itself, nudged up by the
78 // rounding mode. Forming the bracket [1 + x^2/2, 1 + x^2/2 + x^4] exactly would say the same,
79 // at the cost of a dense `Rational` of about 2 |EXP(x)| bits -- 14 seconds for x =
80 // 2^-536870908.
81 if -(exp_x << 1) > i64::exact_from(prec) + 1 {
82 return round_from_below(Float::one_prec(prec), Equal, false, rm);
83 }
84 reciprocal_ziv_loop(prec, rm, |m| cos_rational_helper(x, m, Down).0)
85}
86
87// The exact and closed-form values of sec(2 pi q) at the eighths and twelfths of a turn, where the
88// cosine is 0, ±1, ±1/2, ±sqrt(2)/2, or ±sqrt(3)/2. Returns `None` when q is none of them, or
89// when only an inexact value is available and `rm` is `Exact`.
90fn sec_turns_special_case(q: &Rational, prec: u64, rm: RoundingMode) -> Option<(Float, Ordering)> {
91 let d = q.denominator_ref();
92 if *d > 12u32 {
93 return None;
94 }
95 let d = u64::exact_from(d);
96 let negative = *q < 0u32;
97 // the angle in units of 1/d of a turn (the numerator of a `Rational` is unsigned, so the sign
98 // is restored before reducing modulo d)
99 let n = u64::exact_from(
100 &Integer::from_sign_and_abs_ref(!negative, q.numerator_ref()).mod_op(Integer::from(d)),
101 );
102 match d {
103 // eighths of a turn; n cannot be 0, since 0 < |q| < 1
104 2 | 4 | 8 => match n * (8 / d) {
105 // sec(180°) = -1
106 4 => Some((-Float::one_prec(prec), Equal)),
107 // The poles at 90° and 270°. The cosine returns +0.0 at both, so its reciprocal is
108 // +infinity at both; that keeps the secant the exact reciprocal of the cosine, and
109 // keeps it even, which taking the sign of the approach would not.
110 2 | 6 => Some((Float::INFINITY, Equal)),
111 _ if rm == Exact => None,
112 // sec(45°) = sec(315°) = sqrt(2), sec(135°) = sec(225°) = -sqrt(2)
113 1 | 7 => Some(signed_constant(Float::sqrt_2_prec_round, false, prec, rm)),
114 _ => Some(signed_constant(Float::sqrt_2_prec_round, true, prec, rm)),
115 },
116 // twelfths of a turn
117 3 | 6 | 12 => match n * (12 / d) {
118 // sec(60°) = sec(300°) = 2, sec(120°) = sec(240°) = -2
119 2 | 10 => Some((Float::one_prec(prec) << 1u32, Equal)),
120 4 | 8 => Some((-(Float::one_prec(prec) << 1u32), Equal)),
121 _ if rm == Exact => None,
122 // sec(30°) = sec(330°) = 2 sqrt(3)/3, sec(150°) = sec(210°) = -2 sqrt(3)/3.
123 // Doubling is exact, so the correctly rounded constant stays correctly rounded.
124 1 | 11 => Some(doubled(signed_constant(
125 Float::sqrt_3_over_3_prec_round,
126 false,
127 prec,
128 rm,
129 ))),
130 _ => Some(doubled(signed_constant(
131 Float::sqrt_3_over_3_prec_round,
132 true,
133 prec,
134 rm,
135 ))),
136 },
137 _ if rm == Exact => None,
138 // Fifths and tenths of a turn, where the cosine is ±phi/2 or ±(phi - 1)/2, so the secant
139 // is ±2(phi - 1) or ±2 phi. sec(72°) = 2 phi, sec(144°) = -2(phi - 1)
140 5 => Some(if n == 1 || n == 4 {
141 doubled(signed_constant(Float::phi_prec_round, false, prec, rm))
142 } else {
143 doubled(signed_constant(phi_minus_1_prec_round, true, prec, rm))
144 }),
145 // sec(36°) = 2(phi - 1), sec(108°) = -2 phi
146 10 => Some(if n == 1 || n == 9 {
147 doubled(signed_constant(phi_minus_1_prec_round, false, prec, rm))
148 } else {
149 doubled(signed_constant(Float::phi_prec_round, true, prec, rm))
150 }),
151 _ => None,
152 }
153}
154
155// Multiplies a correctly rounded value by 2, which is exact and so leaves the `Ordering` alone.
156pub(crate) fn doubled((x, o): (Float, Ordering)) -> (Float, Ordering) {
157 (x << 1u32, o)
158}
159
160// Computes sec(2 pi x/u) for a finite nonzero `Float` x and a nonzero u. This has no MPFR
161// counterpart; it is `sec` with the cosine taken in uths of a turn, which reduces the argument
162// exactly rather than modulo an approximation of 2 pi, and so reaches the exact and closed-form
163// cases that the radian version cannot see.
164fn sec_with_period_prec_round_normal_ref(
165 x: &Float,
166 u: u64,
167 prec: u64,
168 rm: RoundingMode,
169) -> (Float, Ordering) {
170 // Range reduction, as in `tan_with_period`: the argument is already reduced if |x| < u.
171 let xr;
172 let xp = if x.lt_abs(&u) {
173 x
174 } else {
175 // xr = x mod u, with the sign of x, exactly
176 let p = i64::exact_from(x.get_prec().unwrap()) - i64::from(x.get_exponent().unwrap());
177 let (r, o) =
178 x.rem_unsigned_prec_round_ref(u, u64::WIDTH + u64::exact_from(max(p, 0)), Exact);
179 assert_eq!(o, Equal);
180 if r == 0u32 {
181 // x is a multiple of u, so the cosine is 1 and the secant is 1
182 return (Float::one_prec(prec), Equal);
183 }
184 xr = r;
185 &xr
186 };
187 // now |xp/u| < 1
188 let exp_x = i64::from(xp.get_exponent().unwrap());
189 // The special cases need |x/u| >= 1/12, so the exponent test skips the `Rational` construction
190 // for the small x that would make it expensive (a tiny x has a huge power-of-2 denominator).
191 if exp_x >= i64::exact_from(u.significant_bits()) - 4
192 && let Some(result) =
193 sec_turns_special_case(&(Rational::exact_from(xp) / Rational::from(u)), prec, rm)
194 {
195 return result;
196 }
197 // Only the exact cases can be rounded exactly
198 assert_ne!(rm, Exact, "Inexact sec_with_period");
199 // u >= 2^log2u, so |2 pi x/u| < 2^(exp_x + 3 - log2u)
200 let log2u = if u == 1 {
201 0
202 } else {
203 i64::exact_from(u.ceiling_log_base_2()) - 1
204 };
205 let bound = exp_x + 3 - log2u;
206 if bound < 0 {
207 // sec(t) = 1 + t^2/2 + ..., and |sec(t) - 1| < t^2 for |t| <= 1, so the error is below 2^(2
208 // bound). Without this shortcut the loop below would have to raise the working precision to
209 // about twice the angle's exponent, which is unbounded for an angle below the `Float`
210 // exponent range.
211 let err = u64::exact_from(-(bound << 1));
212 if err > prec + 1 {
213 // The reference value 1 has precision 1 < err, so float_round_near_x always succeeds.
214 return float_round_near_x(&Float::ONE, min(err, prec + 2), true, prec, rm).unwrap();
215 }
216 }
217 reciprocal_ziv_loop(prec, rm, |m| {
218 xp.cos_with_period_prec_round_ref(u, m, Down).0
219 })
220}
221
222// Computes sec(2 pi q) for a nonzero fraction of a turn q with |q| < 1, rounded to precision `prec`
223// with rounding mode `rm`. This is the `Rational` counterpart of
224// `sec_with_period_prec_round_normal_ref`, with the same structure: the small-input shortcut, the
225// closed-form cases, and a Ziv loop around the reciprocal of `cos_turns_helper`. `rm` may be
226// `Exact` only in the exact cases.
227fn sec_turns_helper(q: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
228 let exp_q = q.floor_log_base_2_abs() + 1;
229 // sec(t) = 1 + t^2/2 + ... with |sec(t) - 1| < t^2 for |t| <= 1, and |2 pi q| < 2^(exp_q + 3),
230 // so |sec(2 pi q) - 1| < 2^(6 + 2 EXP(q)), and the secant lies above 1
231 let err = -(exp_q << 1) - 6;
232 if err > 0 {
233 let err = u64::exact_from(err);
234 if err > prec + 1 {
235 // As in the `Float` version: the reference value 1 always rounds, the bound need not
236 // exceed prec + 2, and such a tiny q is neither a special case nor exact.
237 assert_ne!(rm, Exact, "Inexact sec_with_period");
238 return float_round_near_x(&Float::ONE, min(err, prec + 2), true, prec, rm).unwrap();
239 }
240 }
241 // The special cases need |q| >= 1/12
242 if exp_q >= -4
243 && let Some(result) = sec_turns_special_case(q, prec, rm)
244 {
245 return result;
246 }
247 // Only the exact cases can be rounded exactly
248 assert_ne!(rm, Exact, "Inexact sec_with_period");
249 reciprocal_ziv_loop(prec, rm, |m| cos_turns_helper(q, m, Down).0)
250}
251
252impl Float {
253 /// Computes $\sec x$, the secant of a [`Float`], rounding the result to the specified precision
254 /// and with the specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is
255 /// also returned, indicating whether the rounded secant is less than, equal to, or greater than
256 /// the exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this
257 /// function returns a `NaN` it also returns `Equal`.
258 ///
259 /// See [`RoundingMode`] for a description of the possible rounding modes.
260 ///
261 /// $$
262 /// f(x,p,m) = \sec x+\varepsilon.
263 /// $$
264 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
265 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec
266 /// x|\rfloor-p+1}$.
267 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec
268 /// x|\rfloor-p}$.
269 ///
270 /// If the output has a precision, it is `prec`.
271 ///
272 /// Special cases:
273 /// - $f(\text{NaN},p,m)=\text{NaN}$
274 /// - $f(\pm\infty,p,m)=\text{NaN}$
275 /// - $f(\pm0.0,p,m)=1.0$
276 ///
277 /// Overflow:
278 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
279 /// returned instead.
280 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
281 /// returned instead.
282 /// - If $f(x,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
283 /// returned instead.
284 /// - If $f(x,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
285 /// is returned instead.
286 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
287 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
288 ///
289 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
290 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes more than $2^{30}$ bits of
291 /// precision.
292 ///
293 /// If you know you'll be using `Nearest`, consider using [`Float::sec_prec`] instead. If you
294 /// know that your target precision is the precision of the input, consider using
295 /// [`Float::sec_round`] instead. If both of these things are true, consider using
296 /// [`Float::sec`] instead.
297 ///
298 /// # Worst-case complexity
299 /// $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))$
300 ///
301 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
302 ///
303 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
304 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
305 /// a negative one): the cosine at working precision $n$, summed by binary splitting of the
306 /// Taylor series for large $n$, and its reciprocal cost the first term, and for $|x| \geq 4$
307 /// the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n + e$ bits and a
308 /// remainder of the $m$-bit input. Unlike most functions, `sec` therefore gets slower as the
309 /// magnitude of its input grows, not just as the precision does.
310 ///
311 /// # Panics
312 /// Panics if `rm` is `Exact`, since the secant of a finite nonzero [`Float`] is never exactly
313 /// representable, or if `prec` is zero.
314 ///
315 /// # Examples
316 /// ```
317 /// use malachite_base::rounding_modes::RoundingMode::*;
318 /// use malachite_float::Float;
319 /// use std::cmp::Ordering::*;
320 ///
321 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
322 /// .0
323 /// .sec_prec_round(5, Floor);
324 /// assert_eq!(c.to_string(), "1.81");
325 /// assert_eq!(o, Less);
326 ///
327 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
328 /// .0
329 /// .sec_prec_round(5, Ceiling);
330 /// assert_eq!(c.to_string(), "1.88");
331 /// assert_eq!(o, Greater);
332 ///
333 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
334 /// .0
335 /// .sec_prec_round(5, Nearest);
336 /// assert_eq!(c.to_string(), "1.88");
337 /// assert_eq!(o, Greater);
338 ///
339 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
340 /// .0
341 /// .sec_prec_round(20, Floor);
342 /// assert_eq!(c.to_string(), "1.8508148");
343 /// assert_eq!(o, Less);
344 ///
345 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
346 /// .0
347 /// .sec_prec_round(20, Ceiling);
348 /// assert_eq!(c.to_string(), "1.8508167");
349 /// assert_eq!(o, Greater);
350 ///
351 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
352 /// .0
353 /// .sec_prec_round(20, Nearest);
354 /// assert_eq!(c.to_string(), "1.8508148");
355 /// assert_eq!(o, Less);
356 /// ```
357 #[inline]
358 pub fn sec_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
359 self.sec_prec_round_ref(prec, rm)
360 }
361
362 /// Computes $\sec x$, the secant of a [`Float`], rounding the result to the specified precision
363 /// and with the specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`]
364 /// is also returned, indicating whether the rounded secant is less than, equal to, or greater
365 /// than the exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this
366 /// function returns a `NaN` it also returns `Equal`.
367 ///
368 /// See [`RoundingMode`] for a description of the possible rounding modes.
369 ///
370 /// $$
371 /// f(x,p,m) = \sec x+\varepsilon.
372 /// $$
373 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
374 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec
375 /// x|\rfloor-p+1}$.
376 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec
377 /// x|\rfloor-p}$.
378 ///
379 /// If the output has a precision, it is `prec`.
380 ///
381 /// Special cases:
382 /// - $f(\text{NaN},p,m)=\text{NaN}$
383 /// - $f(\pm\infty,p,m)=\text{NaN}$
384 /// - $f(\pm0.0,p,m)=1.0$
385 ///
386 /// Overflow:
387 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
388 /// returned instead.
389 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
390 /// returned instead.
391 /// - If $f(x,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
392 /// returned instead.
393 /// - If $f(x,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
394 /// is returned instead.
395 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
396 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
397 ///
398 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
399 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes more than $2^{30}$ bits of
400 /// precision.
401 ///
402 /// If you know you'll be using `Nearest`, consider using [`Float::sec_prec_ref`] instead. If
403 /// you know that your target precision is the precision of the input, consider using
404 /// [`Float::sec_round_ref`] instead. If both of these things are true, consider using
405 /// `(&Float).sec()` instead.
406 ///
407 /// # Worst-case complexity
408 /// $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))$
409 ///
410 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
411 ///
412 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
413 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
414 /// a negative one): the cosine at working precision $n$, summed by binary splitting of the
415 /// Taylor series for large $n$, and its reciprocal cost the first term, and for $|x| \geq 4$
416 /// the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n + e$ bits and a
417 /// remainder of the $m$-bit input. Unlike most functions, `sec` therefore gets slower as the
418 /// magnitude of its input grows, not just as the precision does.
419 ///
420 /// # Panics
421 /// Panics if `rm` is `Exact`, since the secant of a finite nonzero [`Float`] is never exactly
422 /// representable, or if `prec` is zero.
423 ///
424 /// # Examples
425 /// ```
426 /// use malachite_base::rounding_modes::RoundingMode::*;
427 /// use malachite_float::Float;
428 /// use std::cmp::Ordering::*;
429 ///
430 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_round_ref(5, Floor);
431 /// assert_eq!(c.to_string(), "1.81");
432 /// assert_eq!(o, Less);
433 ///
434 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_round_ref(5, Ceiling);
435 /// assert_eq!(c.to_string(), "1.88");
436 /// assert_eq!(o, Greater);
437 ///
438 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_round_ref(5, Nearest);
439 /// assert_eq!(c.to_string(), "1.88");
440 /// assert_eq!(o, Greater);
441 ///
442 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_round_ref(20, Floor);
443 /// assert_eq!(c.to_string(), "1.8508148");
444 /// assert_eq!(o, Less);
445 ///
446 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_round_ref(20, Ceiling);
447 /// assert_eq!(c.to_string(), "1.8508167");
448 /// assert_eq!(o, Greater);
449 ///
450 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_round_ref(20, Nearest);
451 /// assert_eq!(c.to_string(), "1.8508148");
452 /// assert_eq!(o, Less);
453 /// ```
454 pub fn sec_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
455 assert_ne!(prec, 0);
456 match &self.0 {
457 NaN | Infinity { .. } => (Self::NAN, Equal),
458 // sec(+0) = sec(-0) = 1
459 Zero { .. } => (Self::one_prec(prec), Equal),
460 Finite { .. } => sec_prec_round_normal_ref(self, prec, rm),
461 }
462 }
463
464 /// Computes $\sec x$, the secant of a [`Float`], rounding the result to the nearest value of
465 /// the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned,
466 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
467 /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
468 /// a `NaN` it also returns `Equal`.
469 ///
470 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
471 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
472 /// the `Nearest` rounding mode.
473 ///
474 /// $$
475 /// f(x,p) = \sec x+\varepsilon.
476 /// $$
477 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
478 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$.
479 ///
480 /// If the output has a precision, it is `prec`.
481 ///
482 /// Special cases:
483 /// - $f(\text{NaN},p)=\text{NaN}$
484 /// - $f(\pm\infty,p)=\text{NaN}$
485 /// - $f(\pm0.0,p)=1.0$
486 ///
487 /// Overflow:
488 /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
489 /// - If $f(x,p)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead.
490 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
491 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
492 ///
493 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
494 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes more than $2^{30}$ bits of
495 /// precision.
496 ///
497 /// If you want to use a rounding mode other than `Nearest`, consider using
498 /// [`Float::sec_prec_round`] instead. If you know that your target precision is the precision
499 /// of the input, consider using [`Float::sec`] instead.
500 ///
501 /// # Worst-case complexity
502 /// $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))$
503 ///
504 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
505 ///
506 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
507 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
508 /// a negative one): the cosine at working precision $n$, summed by binary splitting of the
509 /// Taylor series for large $n$, and its reciprocal cost the first term, and for $|x| \geq 4$
510 /// the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n + e$ bits and a
511 /// remainder of the $m$-bit input. Unlike most functions, `sec` therefore gets slower as the
512 /// magnitude of its input grows, not just as the precision does.
513 ///
514 /// # Panics
515 /// Panics if `prec` is zero.
516 ///
517 /// # Examples
518 /// ```
519 /// use malachite_float::Float;
520 /// use std::cmp::Ordering::*;
521 ///
522 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.sec_prec(5);
523 /// assert_eq!(c.to_string(), "1.88");
524 /// assert_eq!(o, Greater);
525 ///
526 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.sec_prec(20);
527 /// assert_eq!(c.to_string(), "1.8508148");
528 /// assert_eq!(o, Less);
529 /// ```
530 #[inline]
531 pub fn sec_prec(self, prec: u64) -> (Self, Ordering) {
532 self.sec_prec_round(prec, Nearest)
533 }
534
535 /// Computes $\sec x$, the secant of a [`Float`], rounding the result to the nearest value of
536 /// the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also
537 /// returned, indicating whether the rounded secant is less than, equal to, or greater than the
538 /// exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this function
539 /// returns a `NaN` it also returns `Equal`.
540 ///
541 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
542 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
543 /// the `Nearest` rounding mode.
544 ///
545 /// $$
546 /// f(x,p) = \sec x+\varepsilon.
547 /// $$
548 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
549 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$.
550 ///
551 /// If the output has a precision, it is `prec`.
552 ///
553 /// Special cases:
554 /// - $f(\text{NaN},p)=\text{NaN}$
555 /// - $f(\pm\infty,p)=\text{NaN}$
556 /// - $f(\pm0.0,p)=1.0$
557 ///
558 /// Overflow:
559 /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
560 /// - If $f(x,p)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead.
561 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
562 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
563 ///
564 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
565 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes more than $2^{30}$ bits of
566 /// precision.
567 ///
568 /// If you want to use a rounding mode other than `Nearest`, consider using
569 /// [`Float::sec_prec_round_ref`] instead. If you know that your target precision is the
570 /// precision of the input, consider using `(&Float).sec()` instead.
571 ///
572 /// # Worst-case complexity
573 /// $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))$
574 ///
575 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
576 ///
577 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
578 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
579 /// a negative one): the cosine at working precision $n$, summed by binary splitting of the
580 /// Taylor series for large $n$, and its reciprocal cost the first term, and for $|x| \geq 4$
581 /// the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n + e$ bits and a
582 /// remainder of the $m$-bit input. Unlike most functions, `sec` therefore gets slower as the
583 /// magnitude of its input grows, not just as the precision does.
584 ///
585 /// # Panics
586 /// Panics if `prec` is zero.
587 ///
588 /// # Examples
589 /// ```
590 /// use malachite_float::Float;
591 /// use std::cmp::Ordering::*;
592 ///
593 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_ref(5);
594 /// assert_eq!(c.to_string(), "1.88");
595 /// assert_eq!(o, Greater);
596 ///
597 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_prec_ref(20);
598 /// assert_eq!(c.to_string(), "1.8508148");
599 /// assert_eq!(o, Less);
600 /// ```
601 #[inline]
602 pub fn sec_prec_ref(&self, prec: u64) -> (Self, Ordering) {
603 self.sec_prec_round_ref(prec, Nearest)
604 }
605
606 /// Computes $\sec x$, the secant of a [`Float`], rounding the result with the specified
607 /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating
608 /// whether the rounded secant is less than, equal to, or greater than the exact secant.
609 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
610 /// it also returns `Equal`.
611 ///
612 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
613 /// description of the possible rounding modes.
614 ///
615 /// $$
616 /// f(x,m) = \sec x+\varepsilon.
617 /// $$
618 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
619 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec
620 /// x|\rfloor-p+1}$, where $p$ is the precision of the input.
621 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec
622 /// x|\rfloor-p}$, where $p$ is the precision of the input.
623 ///
624 /// If the output has a precision, it is the precision of the input.
625 ///
626 /// Special cases:
627 /// - $f(\text{NaN},m)=\text{NaN}$
628 /// - $f(\pm\infty,m)=\text{NaN}$
629 /// - $f(\pm0.0,m)=1.0$
630 ///
631 /// Overflow:
632 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
633 /// returned instead.
634 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
635 /// returned instead.
636 /// - If $f(x,m)\leq -2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
637 /// returned instead.
638 /// - If $f(x,m)\leq -2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
639 /// is returned instead.
640 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
641 /// - If $-2^{-2^{30}-1}\leq f(x,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
642 ///
643 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
644 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes more than $2^{30}$ bits of
645 /// precision.
646 ///
647 /// If you want to specify an output precision, consider using [`Float::sec_prec_round`]
648 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
649 /// [`Float::sec`] instead.
650 ///
651 /// # Worst-case complexity
652 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
653 ///
654 /// $M(n, e) = O((n+e) \log (n+e))$
655 ///
656 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
657 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
658 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
659 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
660 /// e$ bits. Unlike most functions, `sec` therefore gets slower as the magnitude of its input
661 /// grows, not just as the precision does.
662 ///
663 /// # Panics
664 /// Panics if `rm` is `Exact`, since the secant of a finite nonzero [`Float`] is never exactly
665 /// representable.
666 ///
667 /// # Examples
668 /// ```
669 /// use malachite_base::rounding_modes::RoundingMode::*;
670 /// use malachite_float::Float;
671 /// use std::cmp::Ordering::*;
672 ///
673 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.sec_round(Floor);
674 /// assert_eq!(c.to_string(), "1.8508157176809256179117532413979");
675 /// assert_eq!(o, Less);
676 ///
677 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.sec_round(Ceiling);
678 /// assert_eq!(c.to_string(), "1.8508157176809256179117532413995");
679 /// assert_eq!(o, Greater);
680 ///
681 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.sec_round(Nearest);
682 /// assert_eq!(c.to_string(), "1.8508157176809256179117532413979");
683 /// assert_eq!(o, Less);
684 /// ```
685 #[inline]
686 pub fn sec_round(self, rm: RoundingMode) -> (Self, Ordering) {
687 let prec = self.significant_bits();
688 self.sec_prec_round(prec, rm)
689 }
690
691 /// Computes $\sec x$, the secant of a [`Float`], rounding the result with the specified
692 /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned,
693 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
694 /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
695 /// a `NaN` it also returns `Equal`.
696 ///
697 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
698 /// description of the possible rounding modes.
699 ///
700 /// $$
701 /// f(x,m) = \sec x+\varepsilon.
702 /// $$
703 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
704 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec
705 /// x|\rfloor-p+1}$, where $p$ is the precision of the input.
706 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec
707 /// x|\rfloor-p}$, where $p$ is the precision of the input.
708 ///
709 /// If the output has a precision, it is the precision of the input.
710 ///
711 /// Special cases:
712 /// - $f(\text{NaN},m)=\text{NaN}$
713 /// - $f(\pm\infty,m)=\text{NaN}$
714 /// - $f(\pm0.0,m)=1.0$
715 ///
716 /// Overflow:
717 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
718 /// returned instead.
719 /// - If $f(x,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
720 /// returned instead.
721 /// - If $f(x,m)\leq -2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
722 /// returned instead.
723 /// - If $f(x,m)\leq -2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
724 /// is returned instead.
725 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
726 /// - If $-2^{-2^{30}-1}\leq f(x,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
727 ///
728 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
729 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes more than $2^{30}$ bits of
730 /// precision.
731 ///
732 /// If you want to specify an output precision, consider using [`Float::sec_prec_round_ref`]
733 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
734 /// `(&Float).sec()` instead.
735 ///
736 /// # Worst-case complexity
737 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
738 ///
739 /// $M(n, e) = O((n+e) \log (n+e))$
740 ///
741 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
742 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
743 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
744 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
745 /// e$ bits. Unlike most functions, `sec` therefore gets slower as the magnitude of its input
746 /// grows, not just as the precision does.
747 ///
748 /// # Panics
749 /// Panics if `rm` is `Exact`, since the secant of a finite nonzero [`Float`] is never exactly
750 /// representable.
751 ///
752 /// # Examples
753 /// ```
754 /// use malachite_base::rounding_modes::RoundingMode::*;
755 /// use malachite_float::Float;
756 /// use std::cmp::Ordering::*;
757 ///
758 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_round_ref(Floor);
759 /// assert_eq!(c.to_string(), "1.8508157176809256179117532413979");
760 /// assert_eq!(o, Less);
761 ///
762 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_round_ref(Ceiling);
763 /// assert_eq!(c.to_string(), "1.8508157176809256179117532413995");
764 /// assert_eq!(o, Greater);
765 ///
766 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).sec_round_ref(Nearest);
767 /// assert_eq!(c.to_string(), "1.8508157176809256179117532413979");
768 /// assert_eq!(o, Less);
769 /// ```
770 #[inline]
771 pub fn sec_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
772 self.sec_prec_round_ref(self.significant_bits(), rm)
773 }
774
775 /// Computes $\sec x$, the secant of a [`Float`], rounding the result to the specified precision
776 /// and with the specified rounding mode. The [`Float`] is replaced by the result, and an
777 /// [`Ordering`] is returned, indicating whether the rounded secant is less than, equal to, or
778 /// greater than the exact secant. Although `NaN`s are not comparable to any [`Float`], whenever
779 /// this function sets a `NaN` it also returns `Equal`.
780 ///
781 /// See [`RoundingMode`] for a description of the possible rounding modes.
782 ///
783 /// $$
784 /// x \gets \sec x+\varepsilon.
785 /// $$
786 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
787 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec
788 /// x|\rfloor-p+1}$.
789 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec
790 /// x|\rfloor-p}$.
791 ///
792 /// If the output has a precision, it is `prec`.
793 ///
794 /// See the [`Float::sec_prec_round`] documentation for information on special cases and
795 /// overflow.
796 ///
797 /// If you know you'll be using `Nearest`, consider using [`Float::sec_prec_assign`] instead. If
798 /// you know that your target precision is the precision of the input, consider using
799 /// [`Float::sec_round_assign`] instead. If both of these things are true, consider using
800 /// [`Float::sec_assign`] instead.
801 ///
802 /// # Worst-case complexity
803 /// $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))$
804 ///
805 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
806 ///
807 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
808 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
809 /// a negative one): the cosine at working precision $n$, summed by binary splitting of the
810 /// Taylor series for large $n$, and its reciprocal cost the first term, and for $|x| \geq 4$
811 /// the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n + e$ bits and a
812 /// remainder of the $m$-bit input. Unlike most functions, `sec` therefore gets slower as the
813 /// magnitude of its input grows, not just as the precision does.
814 ///
815 /// # Panics
816 /// Panics if `rm` is `Exact`, since the secant of a finite nonzero [`Float`] is never exactly
817 /// representable, or if `prec` is zero.
818 ///
819 /// # Examples
820 /// ```
821 /// use malachite_base::rounding_modes::RoundingMode::*;
822 /// use malachite_float::Float;
823 /// use std::cmp::Ordering::*;
824 ///
825 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
826 /// assert_eq!(x.sec_prec_round_assign(5, Floor), Less);
827 /// assert_eq!(x.to_string(), "1.81");
828 ///
829 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
830 /// assert_eq!(x.sec_prec_round_assign(5, Ceiling), Greater);
831 /// assert_eq!(x.to_string(), "1.88");
832 ///
833 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
834 /// assert_eq!(x.sec_prec_round_assign(5, Nearest), Greater);
835 /// assert_eq!(x.to_string(), "1.88");
836 ///
837 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
838 /// assert_eq!(x.sec_prec_round_assign(20, Floor), Less);
839 /// assert_eq!(x.to_string(), "1.8508148");
840 ///
841 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
842 /// assert_eq!(x.sec_prec_round_assign(20, Ceiling), Greater);
843 /// assert_eq!(x.to_string(), "1.8508167");
844 ///
845 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
846 /// assert_eq!(x.sec_prec_round_assign(20, Nearest), Less);
847 /// assert_eq!(x.to_string(), "1.8508148");
848 /// ```
849 #[inline]
850 pub fn sec_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
851 let o;
852 (*self, o) = self.sec_prec_round_ref(prec, rm);
853 o
854 }
855
856 /// Computes $\sec x$, the secant of a [`Float`], rounding the result to the nearest value of
857 /// the specified precision. The [`Float`] is replaced by the result, and an [`Ordering`] is
858 /// returned, indicating whether the rounded secant is less than, equal to, or greater than the
859 /// exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this function
860 /// sets a `NaN` it also returns `Equal`.
861 ///
862 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
863 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
864 /// the `Nearest` rounding mode.
865 ///
866 /// $$
867 /// x \gets \sec x+\varepsilon.
868 /// $$
869 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
870 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$.
871 ///
872 /// If the output has a precision, it is `prec`.
873 ///
874 /// See the [`Float::sec_prec`] documentation for information on special cases and overflow.
875 ///
876 /// If you want to use a rounding mode other than `Nearest`, consider using
877 /// [`Float::sec_prec_round_assign`] instead. If you know that your target precision is the
878 /// precision of the input, consider using [`Float::sec_assign`] instead.
879 ///
880 /// # Worst-case complexity
881 /// $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))$
882 ///
883 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
884 ///
885 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
886 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
887 /// a negative one): the cosine at working precision $n$, summed by binary splitting of the
888 /// Taylor series for large $n$, and its reciprocal cost the first term, and for $|x| \geq 4$
889 /// the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n + e$ bits and a
890 /// remainder of the $m$-bit input. Unlike most functions, `sec` therefore gets slower as the
891 /// magnitude of its input grows, not just as the precision does.
892 ///
893 /// # Panics
894 /// Panics if `prec` is zero.
895 ///
896 /// # Examples
897 /// ```
898 /// use malachite_float::Float;
899 /// use std::cmp::Ordering::*;
900 ///
901 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
902 /// assert_eq!(x.sec_prec_assign(5), Greater);
903 /// assert_eq!(x.to_string(), "1.88");
904 ///
905 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
906 /// assert_eq!(x.sec_prec_assign(20), Less);
907 /// assert_eq!(x.to_string(), "1.8508148");
908 /// ```
909 #[inline]
910 pub fn sec_prec_assign(&mut self, prec: u64) -> Ordering {
911 self.sec_prec_round_assign(prec, Nearest)
912 }
913
914 /// Computes $\sec x$, the secant of a [`Float`], rounding the result with the specified
915 /// rounding mode. The [`Float`] is replaced by the result, and an [`Ordering`] is returned,
916 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
917 /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function sets a
918 /// `NaN` it also returns `Equal`.
919 ///
920 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
921 /// description of the possible rounding modes.
922 ///
923 /// $$
924 /// x \gets \sec x+\varepsilon.
925 /// $$
926 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
927 /// - If $x$ is finite and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec
928 /// x|\rfloor-p+1}$, where $p$ is the precision of the input.
929 /// - If $x$ is finite and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec
930 /// x|\rfloor-p}$, where $p$ is the precision of the input.
931 ///
932 /// If the output has a precision, it is the precision of the input.
933 ///
934 /// See the [`Float::sec_round`] documentation for information on special cases and overflow.
935 ///
936 /// If you want to specify an output precision, consider using [`Float::sec_prec_round_assign`]
937 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
938 /// [`Float::sec_assign`] instead.
939 ///
940 /// # Worst-case complexity
941 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
942 ///
943 /// $M(n, e) = O((n+e) \log (n+e))$
944 ///
945 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
946 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
947 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
948 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
949 /// e$ bits. Unlike most functions, `sec` therefore gets slower as the magnitude of its input
950 /// grows, not just as the precision does.
951 ///
952 /// # Panics
953 /// Panics if `rm` is `Exact`, since the secant of a finite nonzero [`Float`] is never exactly
954 /// representable.
955 ///
956 /// # Examples
957 /// ```
958 /// use malachite_base::rounding_modes::RoundingMode::*;
959 /// use malachite_float::Float;
960 /// use std::cmp::Ordering::*;
961 ///
962 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
963 /// assert_eq!(x.sec_round_assign(Floor), Less);
964 /// assert_eq!(x.to_string(), "1.8508157176809256179117532413979");
965 ///
966 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
967 /// assert_eq!(x.sec_round_assign(Ceiling), Greater);
968 /// assert_eq!(x.to_string(), "1.8508157176809256179117532413995");
969 ///
970 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
971 /// assert_eq!(x.sec_round_assign(Nearest), Less);
972 /// assert_eq!(x.to_string(), "1.8508157176809256179117532413979");
973 /// ```
974 #[inline]
975 pub fn sec_round_assign(&mut self, rm: RoundingMode) -> Ordering {
976 let prec = self.significant_bits();
977 self.sec_prec_round_assign(prec, rm)
978 }
979
980 /// Computes $\sec x$, the secant of a [`Rational`], rounding the result to the specified
981 /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
982 /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the
983 /// rounded secant is less than, equal to, or greater than the exact secant.
984 ///
985 /// See [`RoundingMode`] for a description of the possible rounding modes.
986 ///
987 /// $$
988 /// f(x,p,m) = \sec x+\varepsilon.
989 /// $$
990 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p+1}$.
991 /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec x|\rfloor-p}$.
992 ///
993 /// These bounds do not apply when the result overflows; see below.
994 ///
995 /// The output has precision `prec`.
996 ///
997 /// Special cases:
998 /// - $f(0,p,m)=1$.
999 ///
1000 /// Overflow:
1001 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1002 /// returned instead.
1003 /// - If $f(x,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$ is
1004 /// returned instead.
1005 /// - If $f(x,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
1006 /// returned instead.
1007 /// - If $f(x,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`, $-(1-(1/2)^p)2^{2^{30}-1}$
1008 /// is returned instead.
1009 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1010 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1011 ///
1012 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
1013 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes a denominator of more than $2^{30}$
1014 /// bits.
1015 ///
1016 /// If you know you'll be using `Nearest`, consider using [`Float::sec_rational_prec`] instead.
1017 ///
1018 /// # Worst-case complexity
1019 /// $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))$
1020 ///
1021 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1022 ///
1023 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1024 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1025 /// is rounded to a working precision and its [`Float`] cosine taken there, then reciprocated,
1026 /// which for $|x| \geq 2$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n +
1027 /// e$ bits.
1028 ///
1029 /// # Panics
1030 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1031 /// with the given precision (which is the case for every nonzero input).
1032 ///
1033 /// # Examples
1034 /// ```
1035 /// use malachite_base::rounding_modes::RoundingMode::*;
1036 /// use malachite_float::Float;
1037 /// use malachite_q::Rational;
1038 /// use std::cmp::Ordering::*;
1039 ///
1040 /// let (c, o) = Float::sec_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor);
1041 /// assert_eq!(c.to_string(), "1.19");
1042 /// assert_eq!(o, Less);
1043 ///
1044 /// let (c, o) = Float::sec_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1045 /// assert_eq!(c.to_string(), "1.25");
1046 /// assert_eq!(o, Greater);
1047 ///
1048 /// let (c, o) = Float::sec_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Floor);
1049 /// assert_eq!(c.to_string(), "1.2116280");
1050 /// assert_eq!(o, Less);
1051 ///
1052 /// let (c, o) = Float::sec_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Ceiling);
1053 /// assert_eq!(c.to_string(), "1.2116299");
1054 /// assert_eq!(o, Greater);
1055 /// ```
1056 #[inline]
1057 #[allow(clippy::needless_pass_by_value)]
1058 pub fn sec_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
1059 Self::sec_rational_prec_round_ref(&x, prec, rm)
1060 }
1061
1062 /// Computes $\sec x$, the secant of a [`Rational`], rounding the result to the specified
1063 /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
1064 /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the
1065 /// rounded secant is less than, equal to, or greater than the exact secant.
1066 ///
1067 /// See [`RoundingMode`] for a description of the possible rounding modes.
1068 ///
1069 /// $$
1070 /// f(x,p,m) = \sec x+\varepsilon.
1071 /// $$
1072 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p+1}$.
1073 /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec x|\rfloor-p}$.
1074 ///
1075 /// These bounds do not apply when the result overflows.
1076 ///
1077 /// The output has precision `prec`.
1078 ///
1079 /// Special cases:
1080 /// - $f(0,p,m)=1$.
1081 ///
1082 /// See the [`Float::sec_rational_prec_round`] documentation for information on overflow.
1083 ///
1084 /// If you know you'll be using `Nearest`, consider using [`Float::sec_rational_prec_ref`]
1085 /// instead.
1086 ///
1087 /// # Worst-case complexity
1088 /// $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))$
1089 ///
1090 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1091 ///
1092 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1093 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1094 /// is rounded to a working precision and its [`Float`] cosine taken there, then reciprocated,
1095 /// which for $|x| \geq 2$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n +
1096 /// e$ bits.
1097 ///
1098 /// # Panics
1099 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1100 /// with the given precision (which is the case for every nonzero input).
1101 ///
1102 /// # Examples
1103 /// ```
1104 /// use malachite_base::rounding_modes::RoundingMode::*;
1105 /// use malachite_float::Float;
1106 /// use malachite_q::Rational;
1107 /// use std::cmp::Ordering::*;
1108 ///
1109 /// let (c, o) =
1110 /// Float::sec_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Floor);
1111 /// assert_eq!(c.to_string(), "1.19");
1112 /// assert_eq!(o, Less);
1113 ///
1114 /// let (c, o) =
1115 /// Float::sec_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1116 /// assert_eq!(c.to_string(), "1.25");
1117 /// assert_eq!(o, Greater);
1118 ///
1119 /// let (c, o) =
1120 /// Float::sec_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Floor);
1121 /// assert_eq!(c.to_string(), "1.2116280");
1122 /// assert_eq!(o, Less);
1123 ///
1124 /// let (c, o) =
1125 /// Float::sec_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Ceiling);
1126 /// assert_eq!(c.to_string(), "1.2116299");
1127 /// assert_eq!(o, Greater);
1128 /// ```
1129 pub fn sec_rational_prec_round_ref(
1130 x: &Rational,
1131 prec: u64,
1132 rm: RoundingMode,
1133 ) -> (Self, Ordering) {
1134 assert_ne!(prec, 0);
1135 if *x == 0u32 {
1136 // sec(0) = 1, exactly
1137 return (Self::one_prec(prec), Equal);
1138 }
1139 sec_rational_helper(x, prec, rm)
1140 }
1141
1142 /// Computes $\sec x$, the secant of a [`Rational`], rounding the result to the nearest value of
1143 /// the specified precision and returning the result as a [`Float`]. The [`Rational`] is taken
1144 /// by value. An [`Ordering`] is also returned, indicating whether the rounded secant is less
1145 /// than, equal to, or greater than the exact secant.
1146 ///
1147 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1148 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1149 /// the `Nearest` rounding mode.
1150 ///
1151 /// $$
1152 /// f(x,p) = \sec x+\varepsilon,
1153 /// $$
1154 /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec x|\rfloor-p}$ (unless the result overflows;
1155 /// see below).
1156 ///
1157 /// The output has precision `prec`.
1158 ///
1159 /// Special cases:
1160 /// - $f(0,p)=1$.
1161 ///
1162 /// Overflow:
1163 /// - If $f(x,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
1164 /// - If $f(x,p)\leq -2^{2^{30}-1}$, $-\infty$ is returned instead.
1165 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1166 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1167 ///
1168 /// Underflow is not possible, since $|\sec x| \geq 1$. Overflow requires an input within
1169 /// $2^{-2^{30}}$ of an odd multiple of $\pi/2$, which takes a denominator of more than $2^{30}$
1170 /// bits.
1171 ///
1172 /// If you want to use a rounding mode other than `Nearest`, consider using
1173 /// [`Float::sec_rational_prec_round`] instead.
1174 ///
1175 /// # Worst-case complexity
1176 /// $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))$
1177 ///
1178 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1179 ///
1180 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1181 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1182 /// is rounded to a working precision and its [`Float`] cosine taken there, then reciprocated,
1183 /// which for $|x| \geq 2$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n +
1184 /// e$ bits.
1185 ///
1186 /// # Panics
1187 /// Panics if `prec` is zero.
1188 ///
1189 /// # Examples
1190 /// ```
1191 /// use malachite_float::Float;
1192 /// use malachite_q::Rational;
1193 /// use std::cmp::Ordering::*;
1194 ///
1195 /// let (c, o) = Float::sec_rational_prec(Rational::from_unsigneds(3u8, 5), 5);
1196 /// assert_eq!(c.to_string(), "1.19");
1197 /// assert_eq!(o, Less);
1198 ///
1199 /// let (c, o) = Float::sec_rational_prec(Rational::from_unsigneds(3u8, 5), 20);
1200 /// assert_eq!(c.to_string(), "1.2116280");
1201 /// assert_eq!(o, Less);
1202 /// ```
1203 #[inline]
1204 #[allow(clippy::needless_pass_by_value)]
1205 pub fn sec_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
1206 Self::sec_rational_prec_round_ref(&x, prec, Nearest)
1207 }
1208
1209 /// Computes $\sec x$, the secant of a [`Rational`], rounding the result to the nearest value of
1210 /// the specified precision and returning the result as a [`Float`]. The [`Rational`] is taken
1211 /// by reference. An [`Ordering`] is also returned, indicating whether the rounded secant is
1212 /// less than, equal to, or greater than the exact secant.
1213 ///
1214 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1215 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1216 /// the `Nearest` rounding mode.
1217 ///
1218 /// $$
1219 /// f(x,p) = \sec x+\varepsilon,
1220 /// $$
1221 /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec x|\rfloor-p}$ (unless the result
1222 /// overflows).
1223 ///
1224 /// The output has precision `prec`.
1225 ///
1226 /// Special cases:
1227 /// - $f(0,p)=1$.
1228 ///
1229 /// See the [`Float::sec_rational_prec`] documentation for information on overflow.
1230 ///
1231 /// If you want to use a rounding mode other than `Nearest`, consider using
1232 /// [`Float::sec_rational_prec_round_ref`] instead.
1233 ///
1234 /// # Worst-case complexity
1235 /// $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))$
1236 ///
1237 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1238 ///
1239 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is `x.significant_bits()`,
1240 /// and $e$ is `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): the input
1241 /// is rounded to a working precision and its [`Float`] cosine taken there, then reciprocated,
1242 /// which for $|x| \geq 2$ reduces the argument modulo $2\pi$ and so needs $\pi$ to about $n +
1243 /// e$ bits.
1244 ///
1245 /// # Panics
1246 /// Panics if `prec` is zero.
1247 ///
1248 /// # Examples
1249 /// ```
1250 /// use malachite_float::Float;
1251 /// use malachite_q::Rational;
1252 /// use std::cmp::Ordering::*;
1253 ///
1254 /// let (c, o) = Float::sec_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 5);
1255 /// assert_eq!(c.to_string(), "1.19");
1256 /// assert_eq!(o, Less);
1257 ///
1258 /// let (c, o) = Float::sec_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 20);
1259 /// assert_eq!(c.to_string(), "1.2116280");
1260 /// assert_eq!(o, Less);
1261 /// ```
1262 #[inline]
1263 pub fn sec_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
1264 Self::sec_rational_prec_round_ref(x, prec, Nearest)
1265 }
1266
1267 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn, rounding
1268 /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
1269 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded secant is
1270 /// less than, equal to, or greater than the exact secant. Although `NaN`s are not comparable to
1271 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1272 ///
1273 /// See [`RoundingMode`] for a description of the possible rounding modes.
1274 ///
1275 /// $$
1276 /// f(x,u,p,m) = \sec(2\pi x/u)+\varepsilon.
1277 /// $$
1278 /// - If $x$ is not finite, $u=0$, or $x/u$ is an odd multiple of $1/4$, $\varepsilon$ may be
1279 /// ignored or assumed to be 0.
1280 /// - If $x$ is finite, $u\neq 0$, and $m$ is not `Nearest`, then $|\varepsilon| <
1281 /// 2^{\lfloor\log_2 |\sec(2\pi x/u)|\rfloor-p+1}$.
1282 /// - If $x$ is finite, $u\neq 0$, and $m$ is `Nearest`, then $|\varepsilon| \leq
1283 /// 2^{\lfloor\log_2 |\sec(2\pi x/u)|\rfloor-p}$.
1284 ///
1285 /// If the output has a precision, it is `prec`.
1286 ///
1287 /// Special cases:
1288 /// - $f(\text{NaN},u,p,m)=\text{NaN}$
1289 /// - $f(\pm\infty,u,p,m)=\text{NaN}$
1290 /// - $f(x,0,p,m)=\text{NaN}$
1291 /// - $f(\pm0.0,u,p,m)=1.0$
1292 /// - If $x/u$ is an even multiple of $1/2$, the result is exactly $1$, and at an odd multiple
1293 /// exactly $-1$.
1294 /// - If $x/u$ is an odd multiple of $1/4$, the secant has a pole there, and the result is
1295 /// exactly $\infty$: the cosine is $+0.0$ at every such point, and the secant is its
1296 /// reciprocal.
1297 /// - If $x/u$ is an odd multiple of $1/8$, the result is $\pm\sqrt2$.
1298 ///
1299 /// When $x/u$ in lowest terms has denominator 3 or 6, the result is exactly $\pm2$; when it has
1300 /// denominator 5, 8, 10, or 12, the result is $\pm2\varphi$, $\pm\sqrt2$, $\pm2(\varphi-1)$, or
1301 /// $\pm2\sqrt3/3$, computed from a single correctly rounded constant rather than from $\pi$ and
1302 /// a cosine, which is far faster.
1303 ///
1304 /// Overflow:
1305 /// - If $f(x,u,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1306 /// returned instead.
1307 /// - If $f(x,u,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
1308 /// is returned instead.
1309 /// - If $f(x,u,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Floor`, `Up`, or `Nearest`, $-\infty$ is
1310 /// returned instead.
1311 /// - If $f(x,u,p,m)\leq -2^{2^{30}-1}$ and $m$ is `Ceiling` or `Down`,
1312 /// $-(1-(1/2)^p)2^{2^{30}-1}$ is returned instead.
1313 /// - If $0<f(x,u,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1314 /// - If $-2^{-2^{30}-1}\leq f(x,u,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1315 ///
1316 /// Underflow is not possible, since $|\sec(2\pi x/u)| \geq 1$. Overflow requires $x/u$ within
1317 /// $2^{-2^{30}}$ of an odd multiple of $1/4$ without being one, which takes more than $2^{30}$
1318 /// bits of precision.
1319 ///
1320 /// If you know you'll be using `Nearest`, consider using [`Float::sec_with_period_prec`]
1321 /// instead. If you know that your target precision is the precision of the input, consider
1322 /// using [`Float::sec_with_period_round`] instead.
1323 ///
1324 /// # Worst-case complexity
1325 /// $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))$
1326 ///
1327 /// $M(n, m, e) = O((n+m+e) \log (n+m+e))$
1328 ///
1329 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, $m$ is
1330 /// `self.significant_bits()`, and $e$ is the exponent of `self` (0 if `self` has no exponent or
1331 /// a negative one): the argument is reduced modulo $u$ exactly, and the cosine of $2\pi x/u$ is
1332 /// then taken at a working precision of about $n + e$ bits, which needs $\pi$ to that many
1333 /// bits, and reciprocated.
1334 ///
1335 /// # Panics
1336 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1337 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/8$, or $x$ is
1338 /// zero or not finite, or $u$ is zero).
1339 ///
1340 /// # Examples
1341 /// ```
1342 /// use malachite_base::num::basic::traits::One;
1343 /// use malachite_base::rounding_modes::RoundingMode::*;
1344 /// use malachite_float::Float;
1345 /// use std::cmp::Ordering::*;
1346 ///
1347 /// let (t, o) = Float::ONE.sec_with_period_prec_round(7, 10, Floor);
1348 /// assert_eq!(t.to_string(), "1.6035");
1349 /// assert_eq!(o, Less);
1350 ///
1351 /// let (t, o) = Float::ONE.sec_with_period_prec_round(7, 10, Ceiling);
1352 /// assert_eq!(t.to_string(), "1.6055");
1353 /// assert_eq!(o, Greater);
1354 ///
1355 /// // a quarter turn is a pole
1356 /// let (t, o) = Float::from(90u32).sec_with_period_prec_round(360, 10, Exact);
1357 /// assert_eq!(t.to_string(), "Infinity");
1358 /// assert_eq!(o, Equal);
1359 ///
1360 /// // a half turn is exactly -1
1361 /// let (t, o) = Float::from(180u32).sec_with_period_prec_round(360, 10, Exact);
1362 /// assert_eq!(t.to_string(), "-1.0000");
1363 /// assert_eq!(o, Equal);
1364 ///
1365 /// // a twelfth of a turn: 2 sqrt(3)/3
1366 /// let (t, o) = Float::from(30u32).sec_with_period_prec_round(360, 10, Nearest);
1367 /// assert_eq!(t.to_string(), "1.1543");
1368 /// assert_eq!(o, Less);
1369 /// ```
1370 #[inline]
1371 pub fn sec_with_period_prec_round(
1372 self,
1373 u: u64,
1374 prec: u64,
1375 rm: RoundingMode,
1376 ) -> (Self, Ordering) {
1377 self.sec_with_period_prec_round_ref(u, prec, rm)
1378 }
1379
1380 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn, rounding
1381 /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
1382 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded secant
1383 /// is less than, equal to, or greater than the exact secant. Although `NaN`s are not comparable
1384 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1385 ///
1386 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1387 /// cases, overflow, and the complexity; this function behaves the same way.
1388 ///
1389 /// # Panics
1390 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1391 /// with the given precision.
1392 ///
1393 /// # Examples
1394 /// ```
1395 /// use malachite_base::num::basic::traits::One;
1396 /// use malachite_base::rounding_modes::RoundingMode::*;
1397 /// use malachite_float::Float;
1398 /// use std::cmp::Ordering::*;
1399 ///
1400 /// let (t, o) = Float::ONE.sec_with_period_prec_round_ref(7, 10, Floor);
1401 /// assert_eq!(t.to_string(), "1.6035");
1402 /// assert_eq!(o, Less);
1403 /// ```
1404 pub fn sec_with_period_prec_round_ref(
1405 &self,
1406 u: u64,
1407 prec: u64,
1408 rm: RoundingMode,
1409 ) -> (Self, Ordering) {
1410 assert_ne!(prec, 0);
1411 match &self.0 {
1412 // for u=0, return NaN
1413 _ if u == 0 => (Self::NAN, Equal),
1414 NaN | Infinity { .. } => (Self::NAN, Equal),
1415 // x is zero: sec(±0) = 1
1416 Zero { .. } => (Self::one_prec(prec), Equal),
1417 Finite { .. } => sec_with_period_prec_round_normal_ref(self, u, prec, rm),
1418 }
1419 }
1420
1421 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn, rounding
1422 /// the result to the nearest value of the specified precision. The [`Float`] is taken by value.
1423 /// An [`Ordering`] is also returned, indicating whether the rounded secant is less than, equal
1424 /// to, or greater than the exact secant. Although `NaN`s are not comparable to any [`Float`],
1425 /// whenever this function returns a `NaN` it also returns `Equal`.
1426 ///
1427 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1428 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1429 /// the `Nearest` rounding mode.
1430 ///
1431 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1432 /// cases, overflow, and the complexity; this function behaves the same way with `Nearest`.
1433 ///
1434 /// If you want to use a rounding mode other than `Nearest`, consider using
1435 /// [`Float::sec_with_period_prec_round`] instead.
1436 ///
1437 /// # Panics
1438 /// Panics if `prec` is zero.
1439 ///
1440 /// # Examples
1441 /// ```
1442 /// use malachite_base::num::basic::traits::One;
1443 /// use malachite_float::Float;
1444 /// use std::cmp::Ordering::*;
1445 ///
1446 /// let (t, o) = Float::ONE.sec_with_period_prec(7, 10);
1447 /// assert_eq!(t.to_string(), "1.6035");
1448 /// assert_eq!(o, Less);
1449 ///
1450 /// // an eighth of a turn: sqrt(2)
1451 /// let (t, o) = Float::ONE.sec_with_period_prec(8, 10);
1452 /// assert_eq!(t.to_string(), "1.4141");
1453 /// assert_eq!(o, Less);
1454 /// ```
1455 #[inline]
1456 pub fn sec_with_period_prec(self, u: u64, prec: u64) -> (Self, Ordering) {
1457 self.sec_with_period_prec_round(u, prec, Nearest)
1458 }
1459
1460 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn, rounding
1461 /// the result to the nearest value of the specified precision. The [`Float`] is taken by
1462 /// reference. An [`Ordering`] is also returned, indicating whether the rounded secant is less
1463 /// than, equal to, or greater than the exact secant. Although `NaN`s are not comparable to any
1464 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1465 ///
1466 /// See [`Float::sec_with_period_prec`] and [`Float::sec_with_period_prec_round`]; this function
1467 /// behaves the same way.
1468 ///
1469 /// # Panics
1470 /// Panics if `prec` is zero.
1471 ///
1472 /// # Examples
1473 /// ```
1474 /// use malachite_base::num::basic::traits::One;
1475 /// use malachite_float::Float;
1476 /// use std::cmp::Ordering::*;
1477 ///
1478 /// let (t, o) = Float::ONE.sec_with_period_prec_ref(7, 10);
1479 /// assert_eq!(t.to_string(), "1.6035");
1480 /// assert_eq!(o, Less);
1481 /// ```
1482 #[inline]
1483 pub fn sec_with_period_prec_ref(&self, u: u64, prec: u64) -> (Self, Ordering) {
1484 self.sec_with_period_prec_round_ref(u, prec, Nearest)
1485 }
1486
1487 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn, rounding
1488 /// the result to the precision of the input and with the specified rounding mode. The [`Float`]
1489 /// is taken by value. An [`Ordering`] is also returned, indicating whether the rounded secant
1490 /// is less than, equal to, or greater than the exact secant. Although `NaN`s are not comparable
1491 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1492 ///
1493 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1494 /// cases, overflow, and the complexity; this function behaves the same way with `prec` equal to
1495 /// the precision of the input.
1496 ///
1497 /// If you want to specify an output precision, consider using
1498 /// [`Float::sec_with_period_prec_round`] instead.
1499 ///
1500 /// # Panics
1501 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the precision of
1502 /// the input.
1503 ///
1504 /// # Examples
1505 /// ```
1506 /// use malachite_base::rounding_modes::RoundingMode::*;
1507 /// use malachite_float::Float;
1508 /// use std::cmp::Ordering::*;
1509 ///
1510 /// let (t, o) = Float::from_unsigned_prec(1u32, 10)
1511 /// .0
1512 /// .sec_with_period_round(7, Floor);
1513 /// assert_eq!(t.to_string(), "1.6035");
1514 /// assert_eq!(o, Less);
1515 /// ```
1516 #[inline]
1517 pub fn sec_with_period_round(self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
1518 let prec = self.significant_bits();
1519 self.sec_with_period_prec_round(u, prec, rm)
1520 }
1521
1522 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn, rounding
1523 /// the result to the precision of the input and with the specified rounding mode. The [`Float`]
1524 /// is taken by reference. An [`Ordering`] is also returned, indicating whether the rounded
1525 /// secant is less than, equal to, or greater than the exact secant. Although `NaN`s are not
1526 /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1527 ///
1528 /// See [`Float::sec_with_period_round`] and [`Float::sec_with_period_prec_round`]; this
1529 /// function behaves the same way.
1530 ///
1531 /// # Panics
1532 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the precision of
1533 /// the input.
1534 ///
1535 /// # Examples
1536 /// ```
1537 /// use malachite_base::rounding_modes::RoundingMode::*;
1538 /// use malachite_float::Float;
1539 /// use std::cmp::Ordering::*;
1540 ///
1541 /// let (t, o) = Float::from_unsigned_prec(1u32, 10)
1542 /// .0
1543 /// .sec_with_period_round_ref(7, Floor);
1544 /// assert_eq!(t.to_string(), "1.6035");
1545 /// assert_eq!(o, Less);
1546 /// ```
1547 #[inline]
1548 pub fn sec_with_period_round_ref(&self, u: u64, rm: RoundingMode) -> (Self, Ordering) {
1549 self.sec_with_period_prec_round_ref(u, self.significant_bits(), rm)
1550 }
1551
1552 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn (so that
1553 /// `u = 360` is degrees), rounding the result to the precision of the input and to the nearest
1554 /// [`Float`]. The [`Float`] is taken by value.
1555 ///
1556 /// If the secant is equidistant from two [`Float`]s with the precision of the input, the
1557 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1558 /// description of the `Nearest` rounding mode.
1559 ///
1560 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1561 /// cases, overflow, and the complexity; this function behaves the same way with `prec` equal to
1562 /// the precision of the input and `rm` equal to `Nearest`.
1563 ///
1564 /// If you want to use a rounding mode other than `Nearest`, consider using
1565 /// [`Float::sec_with_period_round`] instead. If you want to specify an output precision,
1566 /// consider using [`Float::sec_with_period_prec`]. If you want both of these things, consider
1567 /// using [`Float::sec_with_period_prec_round`].
1568 ///
1569 /// # Examples
1570 /// ```
1571 /// use malachite_float::Float;
1572 ///
1573 /// let t = Float::from_unsigned_prec(1u32, 10).0.sec_with_period(7);
1574 /// assert_eq!(t.to_string(), "1.6035");
1575 ///
1576 /// // a quarter turn is a pole
1577 /// assert_eq!(
1578 /// Float::from(90u32).sec_with_period(360).to_string(),
1579 /// "Infinity"
1580 /// );
1581 /// ```
1582 #[inline]
1583 pub fn sec_with_period(self, u: u64) -> Self {
1584 let prec = self.significant_bits();
1585 self.sec_with_period_prec(u, prec).0
1586 }
1587
1588 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn (so that
1589 /// `u = 360` is degrees), rounding the result to the precision of the input and to the nearest
1590 /// [`Float`]. The [`Float`] is taken by reference.
1591 ///
1592 /// If the secant is equidistant from two [`Float`]s with the precision of the input, the
1593 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1594 /// description of the `Nearest` rounding mode.
1595 ///
1596 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1597 /// cases, overflow, and the complexity; this function behaves the same way with `prec` equal to
1598 /// the precision of the input and `rm` equal to `Nearest`.
1599 ///
1600 /// If you want to use a rounding mode other than `Nearest`, consider using
1601 /// [`Float::sec_with_period_round_ref`] instead. If you want to specify an output precision,
1602 /// consider using [`Float::sec_with_period_prec_ref`]. If you want both of these things,
1603 /// consider using [`Float::sec_with_period_prec_round_ref`].
1604 ///
1605 /// # Examples
1606 /// ```
1607 /// use malachite_float::Float;
1608 ///
1609 /// let t = (&Float::from_unsigned_prec(1u32, 10).0).sec_with_period_ref(7);
1610 /// assert_eq!(t.to_string(), "1.6035");
1611 /// ```
1612 #[inline]
1613 pub fn sec_with_period_ref(&self, u: u64) -> Self {
1614 self.sec_with_period_prec_ref(u, self.significant_bits()).0
1615 }
1616
1617 /// Replaces a [`Float`] measured in $u$ths of a turn with its secant, rounding the result to
1618 /// the specified precision and with the specified rounding mode. An [`Ordering`] is returned,
1619 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
1620 /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function sets a
1621 /// `NaN` it also returns `Equal`.
1622 ///
1623 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1624 /// cases, overflow, and the complexity; this function behaves the same way.
1625 ///
1626 /// # Panics
1627 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1628 /// with the given precision.
1629 ///
1630 /// # Examples
1631 /// ```
1632 /// use malachite_base::num::basic::traits::One;
1633 /// use malachite_base::rounding_modes::RoundingMode::*;
1634 /// use malachite_float::Float;
1635 /// use std::cmp::Ordering::*;
1636 ///
1637 /// let mut x = Float::ONE;
1638 /// assert_eq!(x.sec_with_period_prec_round_assign(7, 10, Floor), Less);
1639 /// assert_eq!(x.to_string(), "1.6035");
1640 /// ```
1641 #[inline]
1642 pub fn sec_with_period_prec_round_assign(
1643 &mut self,
1644 u: u64,
1645 prec: u64,
1646 rm: RoundingMode,
1647 ) -> Ordering {
1648 let (t, o) = self.sec_with_period_prec_round_ref(u, prec, rm);
1649 *self = t;
1650 o
1651 }
1652
1653 /// Replaces a [`Float`] measured in $u$ths of a turn with its secant, rounding the result to
1654 /// the nearest value of the specified precision. An [`Ordering`] is returned, indicating
1655 /// whether the rounded secant is less than, equal to, or greater than the exact secant.
1656 /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it
1657 /// also returns `Equal`.
1658 ///
1659 /// See [`Float::sec_with_period_prec`] and [`Float::sec_with_period_prec_round`]; this function
1660 /// behaves the same way.
1661 ///
1662 /// # Panics
1663 /// Panics if `prec` is zero.
1664 ///
1665 /// # Examples
1666 /// ```
1667 /// use malachite_base::num::basic::traits::One;
1668 /// use malachite_float::Float;
1669 /// use std::cmp::Ordering::*;
1670 ///
1671 /// let mut x = Float::ONE;
1672 /// assert_eq!(x.sec_with_period_prec_assign(7, 10), Less);
1673 /// assert_eq!(x.to_string(), "1.6035");
1674 /// ```
1675 #[inline]
1676 pub fn sec_with_period_prec_assign(&mut self, u: u64, prec: u64) -> Ordering {
1677 self.sec_with_period_prec_round_assign(u, prec, Nearest)
1678 }
1679
1680 /// Replaces a [`Float`] measured in $u$ths of a turn with its secant, rounding the result to
1681 /// the precision of the input and with the specified rounding mode. An [`Ordering`] is
1682 /// returned, indicating whether the rounded secant is less than, equal to, or greater than the
1683 /// exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this function
1684 /// sets a `NaN` it also returns `Equal`.
1685 ///
1686 /// See [`Float::sec_with_period_round`] and [`Float::sec_with_period_prec_round`]; this
1687 /// function behaves the same way.
1688 ///
1689 /// # Panics
1690 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the precision of
1691 /// the input.
1692 ///
1693 /// # Examples
1694 /// ```
1695 /// use malachite_base::rounding_modes::RoundingMode::*;
1696 /// use malachite_float::Float;
1697 /// use std::cmp::Ordering::*;
1698 ///
1699 /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
1700 /// assert_eq!(x.sec_with_period_round_assign(7, Floor), Less);
1701 /// assert_eq!(x.to_string(), "1.6035");
1702 /// ```
1703 #[inline]
1704 pub fn sec_with_period_round_assign(&mut self, u: u64, rm: RoundingMode) -> Ordering {
1705 let prec = self.significant_bits();
1706 self.sec_with_period_prec_round_assign(u, prec, rm)
1707 }
1708
1709 /// Computes $\sec(2\pi x/u)$, the secant of a [`Float`] measured in $u$ths of a turn (so that
1710 /// `u = 360` is degrees), rounding the result to the precision of the input and to the nearest
1711 /// [`Float`]. The [`Float`] is replaced by the result.
1712 ///
1713 /// If the secant is equidistant from two [`Float`]s with the precision of the input, the
1714 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1715 /// description of the `Nearest` rounding mode.
1716 ///
1717 /// See [`Float::sec_with_period_prec_round`] for the error bounds, the special and closed-form
1718 /// cases, overflow, and the complexity; this function behaves the same way with `prec` equal to
1719 /// the precision of the input and `rm` equal to `Nearest`.
1720 ///
1721 /// If you want to use a rounding mode other than `Nearest`, consider using
1722 /// [`Float::sec_with_period_round_assign`] instead. If you want to specify an output precision,
1723 /// consider using [`Float::sec_with_period_prec_assign`]. If you want both of these things,
1724 /// consider using [`Float::sec_with_period_prec_round_assign`].
1725 ///
1726 /// # Examples
1727 /// ```
1728 /// use malachite_float::Float;
1729 ///
1730 /// let mut x = Float::from_unsigned_prec(1u32, 10).0;
1731 /// x.sec_with_period_assign(7);
1732 /// assert_eq!(x.to_string(), "1.6035");
1733 /// ```
1734 #[inline]
1735 pub fn sec_with_period_assign(&mut self, u: u64) {
1736 let prec = self.significant_bits();
1737 self.sec_with_period_prec_assign(u, prec);
1738 }
1739
1740 /// Computes $\sec(2\pi x/u)$, the secant of a [`Rational`] measured in $u$ths of a turn,
1741 /// rounding the result to the specified precision and with the specified rounding mode, and
1742 /// returning the result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is
1743 /// also returned, indicating whether the rounded secant is less than, equal to, or greater than
1744 /// the exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this
1745 /// function returns a `NaN` it also returns `Equal`.
1746 ///
1747 /// See [`RoundingMode`] for a description of the possible rounding modes.
1748 ///
1749 /// $$
1750 /// f(x,u,p,m) = \sec(2\pi x/u)+\varepsilon.
1751 /// $$
1752 /// - If $u=0$ or $x/u$ is an odd multiple of $1/4$, $\varepsilon$ may be ignored or assumed to
1753 /// be 0.
1754 /// - If $u\neq 0$ and $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec(2\pi
1755 /// x/u)|\rfloor-p+1}$.
1756 /// - If $u\neq 0$ and $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\sec(2\pi
1757 /// x/u)|\rfloor-p}$.
1758 ///
1759 /// If the output has a precision, it is `prec`.
1760 ///
1761 /// Special cases:
1762 /// - $f(x,0,p,m)=\text{NaN}$
1763 /// - $f(0,u,p,m)=1$
1764 /// - If $x/u$ is an even multiple of $1/2$, the result is exactly $1$, and at an odd multiple
1765 /// exactly $-1$.
1766 /// - If $x/u$ is an odd multiple of $1/4$, the secant has a pole there, and the result is
1767 /// exactly $\infty$: the cosine is $+0.0$ at every such point, and the secant is its
1768 /// reciprocal.
1769 /// - If $x/u$ is an odd multiple of $1/8$, the result is $\pm\sqrt2$.
1770 ///
1771 /// When $x/u$ in lowest terms has denominator 3 or 6, the result is exactly $\pm2$; when it has
1772 /// denominator 5, 8, 10, or 12, the result is $\pm2\varphi$, $\pm\sqrt2$, $\pm2(\varphi-1)$, or
1773 /// $\pm2\sqrt3/3$, computed from a single correctly rounded constant rather than from $\pi$ and
1774 /// a cosine, which is far faster.
1775 ///
1776 /// Underflow is not possible, since $|\sec(2\pi x/u)| \geq 1$. Overflow is as for
1777 /// [`Float::sec_with_period_prec_round`], and requires $x/u$ within $2^{-2^{30}}$ of an odd
1778 /// multiple of $1/4$ without being one, which takes a denominator of more than $2^{30}$ bits.
1779 ///
1780 /// If you know you'll be using `Nearest`, consider using
1781 /// [`Float::sec_with_period_rational_prec`] instead.
1782 ///
1783 /// # Worst-case complexity
1784 /// $T(n, m) = O(n (\log n)^3 \log\log n + (n+m) (\log (n+m))^2 \log\log (n+m))$
1785 ///
1786 /// $M(n, m) = O((n+m) \log (n+m))$
1787 ///
1788 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1789 /// `x.significant_bits()`: the fraction of a turn is reduced modulo 1 exactly, so only its size
1790 /// and the precision drive the cost, not the magnitude of $x$.
1791 ///
1792 /// # Panics
1793 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1794 /// with the given precision (which is the case unless $x/u$ is a multiple of $1/8$, or $x$ or
1795 /// $u$ is zero).
1796 ///
1797 /// # Examples
1798 /// ```
1799 /// use malachite_base::num::basic::traits::One;
1800 /// use malachite_base::rounding_modes::RoundingMode::*;
1801 /// use malachite_float::Float;
1802 /// use malachite_q::Rational;
1803 /// use std::cmp::Ordering::*;
1804 ///
1805 /// let (t, o) = Float::sec_with_period_rational_prec_round(Rational::ONE, 7, 10, Floor);
1806 /// assert_eq!(t.to_string(), "1.6035");
1807 /// assert_eq!(o, Less);
1808 ///
1809 /// let (t, o) = Float::sec_with_period_rational_prec_round(Rational::ONE, 7, 10, Ceiling);
1810 /// assert_eq!(t.to_string(), "1.6055");
1811 /// assert_eq!(o, Greater);
1812 ///
1813 /// // a quarter turn is a pole
1814 /// let (t, o) = Float::sec_with_period_rational_prec_round(
1815 /// Rational::from_unsigneds(1u8, 4),
1816 /// 1,
1817 /// 10,
1818 /// Exact,
1819 /// );
1820 /// assert_eq!(t.to_string(), "Infinity");
1821 /// assert_eq!(o, Equal);
1822 ///
1823 /// // a twelfth of a turn: 2 sqrt(3)/3
1824 /// let (t, o) = Float::sec_with_period_rational_prec_round(
1825 /// Rational::from_unsigneds(1u8, 12),
1826 /// 1,
1827 /// 10,
1828 /// Nearest,
1829 /// );
1830 /// assert_eq!(t.to_string(), "1.1543");
1831 /// assert_eq!(o, Less);
1832 /// ```
1833 #[inline]
1834 #[allow(clippy::needless_pass_by_value)]
1835 pub fn sec_with_period_rational_prec_round(
1836 x: Rational,
1837 u: u64,
1838 prec: u64,
1839 rm: RoundingMode,
1840 ) -> (Self, Ordering) {
1841 Self::sec_with_period_rational_prec_round_ref(&x, u, prec, rm)
1842 }
1843
1844 /// Computes $\sec(2\pi x/u)$, the secant of a [`Rational`] measured in $u$ths of a turn,
1845 /// rounding the result to the specified precision and with the specified rounding mode, and
1846 /// returning the result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`]
1847 /// is also returned, indicating whether the rounded secant is less than, equal to, or greater
1848 /// than the exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this
1849 /// function returns a `NaN` it also returns `Equal`.
1850 ///
1851 /// See [`Float::sec_with_period_rational_prec_round`] for the error bounds, the special and
1852 /// closed-form cases, overflow, and the complexity; this function behaves the same way.
1853 ///
1854 /// # Panics
1855 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1856 /// with the given precision.
1857 ///
1858 /// # Examples
1859 /// ```
1860 /// use malachite_base::num::basic::traits::One;
1861 /// use malachite_base::rounding_modes::RoundingMode::*;
1862 /// use malachite_float::Float;
1863 /// use malachite_q::Rational;
1864 /// use std::cmp::Ordering::*;
1865 ///
1866 /// let (t, o) = Float::sec_with_period_rational_prec_round_ref(&Rational::ONE, 7, 10, Floor);
1867 /// assert_eq!(t.to_string(), "1.6035");
1868 /// assert_eq!(o, Less);
1869 /// ```
1870 pub fn sec_with_period_rational_prec_round_ref(
1871 x: &Rational,
1872 u: u64,
1873 prec: u64,
1874 rm: RoundingMode,
1875 ) -> (Self, Ordering) {
1876 assert_ne!(prec, 0);
1877 // for u = 0, return NaN
1878 if u == 0 {
1879 return (Self::NAN, Equal);
1880 }
1881 // sec(0) = 1
1882 if *x == 0u32 {
1883 return (Self::one_prec(prec), Equal);
1884 }
1885 // q = x/u, reduced to (-1, 1): sec(2 pi q) has period 1 in q, and a multiple of u gives a
1886 // cosine of 1, so a secant of 1
1887 let q = x / Rational::from(u) % Rational::ONE;
1888 if q == 0u32 {
1889 return (Self::one_prec(prec), Equal);
1890 }
1891 sec_turns_helper(&q, prec, rm)
1892 }
1893
1894 /// Computes $\sec(2\pi x/u)$, the secant of a [`Rational`] measured in $u$ths of a turn,
1895 /// rounding the result to the nearest value of the specified precision, and returning the
1896 /// result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned,
1897 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
1898 /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
1899 /// a `NaN` it also returns `Equal`.
1900 ///
1901 /// If the secant is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1902 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1903 /// the `Nearest` rounding mode.
1904 ///
1905 /// See [`Float::sec_with_period_rational_prec_round`] for the error bounds, the special and
1906 /// closed-form cases, overflow, and the complexity; this function behaves the same way with
1907 /// `Nearest`.
1908 ///
1909 /// If you want to use a rounding mode other than `Nearest`, consider using
1910 /// [`Float::sec_with_period_rational_prec_round`] instead.
1911 ///
1912 /// # Panics
1913 /// Panics if `prec` is zero.
1914 ///
1915 /// # Examples
1916 /// ```
1917 /// use malachite_base::num::basic::traits::One;
1918 /// use malachite_float::Float;
1919 /// use malachite_q::Rational;
1920 /// use std::cmp::Ordering::*;
1921 ///
1922 /// let (t, o) = Float::sec_with_period_rational_prec(Rational::ONE, 7, 10);
1923 /// assert_eq!(t.to_string(), "1.6035");
1924 /// assert_eq!(o, Less);
1925 ///
1926 /// // an eighth of a turn: sqrt(2)
1927 /// let (t, o) = Float::sec_with_period_rational_prec(Rational::ONE, 8, 10);
1928 /// assert_eq!(t.to_string(), "1.4141");
1929 /// assert_eq!(o, Less);
1930 /// ```
1931 #[inline]
1932 #[allow(clippy::needless_pass_by_value)]
1933 pub fn sec_with_period_rational_prec(x: Rational, u: u64, prec: u64) -> (Self, Ordering) {
1934 Self::sec_with_period_rational_prec_round_ref(&x, u, prec, Nearest)
1935 }
1936
1937 /// Computes $\sec(2\pi x/u)$, the secant of a [`Rational`] measured in $u$ths of a turn,
1938 /// rounding the result to the nearest value of the specified precision, and returning the
1939 /// result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also
1940 /// returned, indicating whether the rounded secant is less than, equal to, or greater than the
1941 /// exact secant. Although `NaN`s are not comparable to any [`Float`], whenever this function
1942 /// returns a `NaN` it also returns `Equal`.
1943 ///
1944 /// See [`Float::sec_with_period_rational_prec`] and
1945 /// [`Float::sec_with_period_rational_prec_round`]; this function behaves the same way.
1946 ///
1947 /// # Panics
1948 /// Panics if `prec` is zero.
1949 ///
1950 /// # Examples
1951 /// ```
1952 /// use malachite_base::num::basic::traits::One;
1953 /// use malachite_float::Float;
1954 /// use malachite_q::Rational;
1955 /// use std::cmp::Ordering::*;
1956 ///
1957 /// let (t, o) = Float::sec_with_period_rational_prec_ref(&Rational::ONE, 7, 10);
1958 /// assert_eq!(t.to_string(), "1.6035");
1959 /// assert_eq!(o, Less);
1960 /// ```
1961 #[inline]
1962 pub fn sec_with_period_rational_prec_ref(x: &Rational, u: u64, prec: u64) -> (Self, Ordering) {
1963 Self::sec_with_period_rational_prec_round_ref(x, u, prec, Nearest)
1964 }
1965
1966 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
1967 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
1968 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded secant is
1969 /// less than, equal to, or greater than the exact secant. Although `NaN`s are not comparable to
1970 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1971 ///
1972 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_prec_round`] for
1973 /// the error bounds, the special and closed-form cases (even integers give $1$ and odd ones
1974 /// $-1$; half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
1975 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
1976 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
1977 /// golden ratio), overflow, and the complexity, with $u = 2$.
1978 ///
1979 /// # Panics
1980 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1981 /// with the given precision.
1982 ///
1983 /// # Examples
1984 /// ```
1985 /// use malachite_base::num::basic::traits::One;
1986 /// use malachite_base::rounding_modes::RoundingMode::*;
1987 /// use malachite_float::Float;
1988 /// use std::cmp::Ordering::*;
1989 ///
1990 /// let (t, o) = Float::from(0.1f64).sec_pi_prec_round(10, Floor);
1991 /// assert_eq!(t.to_string(), "1.0508");
1992 /// assert_eq!(o, Less);
1993 ///
1994 /// let (t, o) = Float::from(0.1f64).sec_pi_prec_round(10, Ceiling);
1995 /// assert_eq!(t.to_string(), "1.0527");
1996 /// assert_eq!(o, Greater);
1997 ///
1998 /// // a half-turn is exactly zero, reached from below
1999 /// let (t, o) = Float::ONE.sec_pi_prec_round(10, Exact);
2000 /// assert_eq!(t.to_string(), "-1.0000");
2001 /// assert_eq!(o, Equal);
2002 /// ```
2003 #[inline]
2004 pub fn sec_pi_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
2005 self.sec_with_period_prec_round(2, prec, rm)
2006 }
2007
2008 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2009 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
2010 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded secant
2011 /// is less than, equal to, or greater than the exact secant. Although `NaN`s are not comparable
2012 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2013 ///
2014 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_prec_round_ref`]
2015 /// for the error bounds, the special and closed-form cases (even integers give $1$ and odd ones
2016 /// $-1$; half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2017 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2018 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2019 /// golden ratio), overflow, and the complexity, with $u = 2$.
2020 ///
2021 /// # Panics
2022 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2023 /// with the given precision.
2024 ///
2025 /// # Examples
2026 /// ```
2027 /// use malachite_base::num::basic::traits::One;
2028 /// use malachite_base::rounding_modes::RoundingMode::*;
2029 /// use malachite_float::Float;
2030 /// use std::cmp::Ordering::*;
2031 ///
2032 /// let (t, o) = (Float::from(0.1f64)).sec_pi_prec_round_ref(10, Floor);
2033 /// assert_eq!(t.to_string(), "1.0508");
2034 /// assert_eq!(o, Less);
2035 ///
2036 /// let (t, o) = (Float::from(0.1f64)).sec_pi_prec_round_ref(10, Ceiling);
2037 /// assert_eq!(t.to_string(), "1.0527");
2038 /// assert_eq!(o, Greater);
2039 ///
2040 /// // a half-turn is exactly zero, reached from below
2041 /// let (t, o) = (&Float::ONE).sec_pi_prec_round_ref(10, Exact);
2042 /// assert_eq!(t.to_string(), "-1.0000");
2043 /// assert_eq!(o, Equal);
2044 /// ```
2045 #[inline]
2046 pub fn sec_pi_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
2047 self.sec_with_period_prec_round_ref(2, prec, rm)
2048 }
2049
2050 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2051 /// result to the nearest value of the specified precision. The [`Float`] is taken by value. An
2052 /// [`Ordering`] is also returned, indicating whether the rounded secant is less than, equal to,
2053 /// or greater than the exact secant. Although `NaN`s are not comparable to any [`Float`],
2054 /// whenever this function returns a `NaN` it also returns `Equal`.
2055 ///
2056 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_prec`] for the
2057 /// error bounds, the special and closed-form cases (even integers give $1$ and odd ones $-1$;
2058 /// half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2059 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2060 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2061 /// golden ratio), overflow, and the complexity, with $u = 2$.
2062 ///
2063 /// # Panics
2064 /// Panics if `prec` is zero.
2065 ///
2066 /// # Examples
2067 /// ```
2068 /// use malachite_float::Float;
2069 /// use std::cmp::Ordering::*;
2070 ///
2071 /// let (t, o) = Float::from(0.1f64).sec_pi_prec(10);
2072 /// assert_eq!(t.to_string(), "1.0508");
2073 /// assert_eq!(o, Less);
2074 ///
2075 /// let (t, o) = Float::from(0.1f64).sec_pi_prec(53);
2076 /// assert_eq!(t.to_string(), "1.0514622242382672");
2077 /// assert_eq!(o, Less);
2078 /// ```
2079 #[inline]
2080 pub fn sec_pi_prec(self, prec: u64) -> (Self, Ordering) {
2081 self.sec_with_period_prec(2, prec)
2082 }
2083
2084 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2085 /// result to the nearest value of the specified precision. The [`Float`] is taken by reference.
2086 /// An [`Ordering`] is also returned, indicating whether the rounded secant is less than, equal
2087 /// to, or greater than the exact secant. Although `NaN`s are not comparable to any [`Float`],
2088 /// whenever this function returns a `NaN` it also returns `Equal`.
2089 ///
2090 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_prec_ref`] for
2091 /// the error bounds, the special and closed-form cases (even integers give $1$ and odd ones
2092 /// $-1$; half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2093 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2094 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2095 /// golden ratio), overflow, and the complexity, with $u = 2$.
2096 ///
2097 /// # Panics
2098 /// Panics if `prec` is zero.
2099 ///
2100 /// # Examples
2101 /// ```
2102 /// use malachite_float::Float;
2103 /// use std::cmp::Ordering::*;
2104 ///
2105 /// let (t, o) = (Float::from(0.1f64)).sec_pi_prec_ref(10);
2106 /// assert_eq!(t.to_string(), "1.0508");
2107 /// assert_eq!(o, Less);
2108 ///
2109 /// let (t, o) = (Float::from(0.1f64)).sec_pi_prec_ref(53);
2110 /// assert_eq!(t.to_string(), "1.0514622242382672");
2111 /// assert_eq!(o, Less);
2112 /// ```
2113 #[inline]
2114 pub fn sec_pi_prec_ref(&self, prec: u64) -> (Self, Ordering) {
2115 self.sec_with_period_prec_ref(2, prec)
2116 }
2117
2118 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2119 /// result with the specified rounding mode. The precision of the output is the precision of the
2120 /// input. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating whether
2121 /// the rounded secant is less than, equal to, or greater than the exact secant. Although `NaN`s
2122 /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
2123 /// `Equal`.
2124 ///
2125 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_round`] for the
2126 /// error bounds, the special and closed-form cases (even integers give $1$ and odd ones $-1$;
2127 /// half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2128 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2129 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2130 /// golden ratio), overflow, and the complexity, with $u = 2$.
2131 ///
2132 /// # Panics
2133 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
2134 /// precision.
2135 ///
2136 /// # Examples
2137 /// ```
2138 /// use malachite_base::rounding_modes::RoundingMode::*;
2139 /// use malachite_float::Float;
2140 /// use std::cmp::Ordering::*;
2141 ///
2142 /// let (t, o) = Float::from(0.1f64).sec_pi_round(Floor);
2143 /// assert_eq!(t.to_string(), "1.0514622242382670");
2144 /// assert_eq!(o, Less);
2145 ///
2146 /// let (t, o) = Float::from(0.1f64).sec_pi_round(Nearest);
2147 /// assert_eq!(t.to_string(), "1.0514622242382674");
2148 /// assert_eq!(o, Greater);
2149 /// ```
2150 #[inline]
2151 pub fn sec_pi_round(self, rm: RoundingMode) -> (Self, Ordering) {
2152 self.sec_with_period_round(2, rm)
2153 }
2154
2155 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2156 /// result with the specified rounding mode. The precision of the output is the precision of the
2157 /// input. The [`Float`] is taken by reference. An [`Ordering`] is also returned, indicating
2158 /// whether the rounded secant is less than, equal to, or greater than the exact secant.
2159 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
2160 /// it also returns `Equal`.
2161 ///
2162 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_round_ref`] for
2163 /// the error bounds, the special and closed-form cases (even integers give $1$ and odd ones
2164 /// $-1$; half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2165 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2166 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2167 /// golden ratio), overflow, and the complexity, with $u = 2$.
2168 ///
2169 /// # Panics
2170 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
2171 /// precision.
2172 ///
2173 /// # Examples
2174 /// ```
2175 /// use malachite_base::rounding_modes::RoundingMode::*;
2176 /// use malachite_float::Float;
2177 /// use std::cmp::Ordering::*;
2178 ///
2179 /// let (t, o) = (Float::from(0.1f64)).sec_pi_round_ref(Floor);
2180 /// assert_eq!(t.to_string(), "1.0514622242382670");
2181 /// assert_eq!(o, Less);
2182 ///
2183 /// let (t, o) = (Float::from(0.1f64)).sec_pi_round_ref(Nearest);
2184 /// assert_eq!(t.to_string(), "1.0514622242382674");
2185 /// assert_eq!(o, Greater);
2186 /// ```
2187 #[inline]
2188 pub fn sec_pi_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
2189 self.sec_with_period_round_ref(2, rm)
2190 }
2191
2192 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2193 /// result to the precision of the input and to the nearest [`Float`]. The [`Float`] is taken by
2194 /// value.
2195 ///
2196 /// If the secant is equidistant from two [`Float`]s with the precision of the input, the
2197 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2198 /// description of the `Nearest` rounding mode.
2199 ///
2200 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period`] for the error
2201 /// bounds, the special and closed-form cases (even integers give $1$ and odd ones $-1$;
2202 /// half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2203 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2204 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2205 /// golden ratio), overflow, and the complexity, with $u = 2$.
2206 ///
2207 /// If you want to use a rounding mode other than `Nearest`, consider using
2208 /// [`Float::sec_pi_round`] instead. If you want to specify an output precision, consider using
2209 /// [`Float::sec_pi_prec`]. If you want both of these things, consider using
2210 /// [`Float::sec_pi_prec_round`].
2211 ///
2212 /// # Examples
2213 /// ```
2214 /// use malachite_float::Float;
2215 ///
2216 /// let t = Float::from(0.1f64).sec_pi();
2217 /// assert_eq!(t.to_string(), "1.0514622242382674");
2218 ///
2219 /// // a half-integer is a pole
2220 /// assert_eq!(Float::from(0.5f64).sec_pi().to_string(), "Infinity");
2221 /// ```
2222 #[inline]
2223 pub fn sec_pi(self) -> Self {
2224 let prec = self.significant_bits();
2225 self.sec_pi_prec(prec).0
2226 }
2227
2228 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2229 /// result to the precision of the input and to the nearest [`Float`]. The [`Float`] is taken by
2230 /// reference.
2231 ///
2232 /// If the secant is equidistant from two [`Float`]s with the precision of the input, the
2233 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2234 /// description of the `Nearest` rounding mode.
2235 ///
2236 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period`] for the error
2237 /// bounds, the special and closed-form cases (even integers give $1$ and odd ones $-1$;
2238 /// half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2239 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2240 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2241 /// golden ratio), overflow, and the complexity, with $u = 2$.
2242 ///
2243 /// If you want to use a rounding mode other than `Nearest`, consider using
2244 /// [`Float::sec_pi_round_ref`] instead. If you want to specify an output precision, consider
2245 /// using [`Float::sec_pi_prec_ref`]. If you want both of these things, consider using
2246 /// [`Float::sec_pi_prec_round_ref`].
2247 ///
2248 /// # Examples
2249 /// ```
2250 /// use malachite_float::Float;
2251 ///
2252 /// let t = (&Float::from(0.1f64)).sec_pi_ref();
2253 /// assert_eq!(t.to_string(), "1.0514622242382674");
2254 /// ```
2255 #[inline]
2256 pub fn sec_pi_ref(&self) -> Self {
2257 self.sec_pi_prec_ref(self.significant_bits()).0
2258 }
2259
2260 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2261 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
2262 /// replaced by the result, and an [`Ordering`] is returned, indicating whether the rounded
2263 /// secant is less than, equal to, or greater than the exact secant. Although `NaN`s are not
2264 /// comparable to any [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
2265 ///
2266 /// This is `sec_with_period` with a period of 2: see
2267 /// [`Float::sec_with_period_prec_round_assign`] for the error bounds, the special and
2268 /// closed-form cases (even integers give $1$ and odd ones $-1$; half-integers are poles and
2269 /// give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$; multiples of $1/3$ give $\pm2$; and
2270 /// odd multiples of $1/6$, and multiples of $1/5$ and $1/10$, give $\pm2\sqrt3/3$,
2271 /// $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the golden ratio), overflow, and the
2272 /// complexity, with $u = 2$.
2273 ///
2274 /// # Panics
2275 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2276 /// with the given precision.
2277 ///
2278 /// # Examples
2279 /// ```
2280 /// use malachite_base::rounding_modes::RoundingMode::*;
2281 /// use malachite_float::Float;
2282 /// use std::cmp::Ordering::*;
2283 ///
2284 /// let mut x = Float::from(0.1f64);
2285 /// assert_eq!(x.sec_pi_prec_round_assign(10, Floor), Less);
2286 /// assert_eq!(x.to_string(), "1.0508");
2287 ///
2288 /// let mut x = Float::from(0.1f64);
2289 /// assert_eq!(x.sec_pi_prec_round_assign(10, Ceiling), Greater);
2290 /// assert_eq!(x.to_string(), "1.0527");
2291 /// ```
2292 #[inline]
2293 pub fn sec_pi_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
2294 self.sec_with_period_prec_round_assign(2, prec, rm)
2295 }
2296
2297 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2298 /// result to the nearest value of the specified precision. The [`Float`] is replaced by the
2299 /// result, and an [`Ordering`] is returned, indicating whether the rounded secant is less than,
2300 /// equal to, or greater than the exact secant. Although `NaN`s are not comparable to any
2301 /// [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
2302 ///
2303 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_prec_assign`] for
2304 /// the error bounds, the special and closed-form cases (even integers give $1$ and odd ones
2305 /// $-1$; half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2306 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2307 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2308 /// golden ratio), overflow, and the complexity, with $u = 2$.
2309 ///
2310 /// # Panics
2311 /// Panics if `prec` is zero.
2312 ///
2313 /// # Examples
2314 /// ```
2315 /// use malachite_float::Float;
2316 /// use std::cmp::Ordering::*;
2317 ///
2318 /// let mut x = Float::from(0.1f64);
2319 /// assert_eq!(x.sec_pi_prec_assign(10), Less);
2320 /// assert_eq!(x.to_string(), "1.0508");
2321 /// ```
2322 #[inline]
2323 pub fn sec_pi_prec_assign(&mut self, prec: u64) -> Ordering {
2324 self.sec_with_period_prec_assign(2, prec)
2325 }
2326
2327 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2328 /// result with the specified rounding mode. The precision of the output is the precision of the
2329 /// input. The [`Float`] is replaced by the result, and an [`Ordering`] is returned, indicating
2330 /// whether the rounded secant is less than, equal to, or greater than the exact secant.
2331 /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it
2332 /// also returns `Equal`.
2333 ///
2334 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period_round_assign`]
2335 /// for the error bounds, the special and closed-form cases (even integers give $1$ and odd ones
2336 /// $-1$; half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2337 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2338 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2339 /// golden ratio), overflow, and the complexity, with $u = 2$.
2340 ///
2341 /// # Panics
2342 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
2343 /// precision.
2344 ///
2345 /// # Examples
2346 /// ```
2347 /// use malachite_base::rounding_modes::RoundingMode::*;
2348 /// use malachite_float::Float;
2349 /// use std::cmp::Ordering::*;
2350 ///
2351 /// let mut x = Float::from(0.1f64);
2352 /// assert_eq!(x.sec_pi_round_assign(Floor), Less);
2353 /// assert_eq!(x.to_string(), "1.0514622242382670");
2354 /// ```
2355 #[inline]
2356 pub fn sec_pi_round_assign(&mut self, rm: RoundingMode) -> Ordering {
2357 self.sec_with_period_round_assign(2, rm)
2358 }
2359
2360 /// Computes $\sec(\pi x)$, the secant of a [`Float`] measured in half-turns, rounding the
2361 /// result to the precision of the input and to the nearest [`Float`]. The [`Float`] is replaced
2362 /// by the result.
2363 ///
2364 /// If the secant is equidistant from two [`Float`]s with the precision of the input, the
2365 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
2366 /// description of the `Nearest` rounding mode.
2367 ///
2368 /// This is `sec_with_period` with a period of 2: see [`Float::sec_with_period`] for the error
2369 /// bounds, the special and closed-form cases (even integers give $1$ and odd ones $-1$;
2370 /// half-integers are poles and give $\infty$; odd multiples of $1/4$ give $\pm\sqrt2$;
2371 /// multiples of $1/3$ give $\pm2$; and odd multiples of $1/6$, and multiples of $1/5$ and
2372 /// $1/10$, give $\pm2\sqrt3/3$, $\pm2\varphi$, or $\pm2(\varphi-1)$, where $\varphi$ is the
2373 /// golden ratio), overflow, and the complexity, with $u = 2$.
2374 ///
2375 /// If you want to use a rounding mode other than `Nearest`, consider using
2376 /// [`Float::sec_pi_round_assign`] instead. If you want to specify an output precision, consider
2377 /// using [`Float::sec_pi_prec_assign`]. If you want both of these things, consider using
2378 /// [`Float::sec_pi_prec_round_assign`].
2379 ///
2380 /// # Examples
2381 /// ```
2382 /// use malachite_float::Float;
2383 ///
2384 /// let mut x = Float::from(0.1f64);
2385 /// x.sec_pi_assign();
2386 /// assert_eq!(x.to_string(), "1.0514622242382674");
2387 /// ```
2388 #[inline]
2389 pub fn sec_pi_assign(&mut self) {
2390 let prec = self.significant_bits();
2391 self.sec_pi_prec_assign(prec);
2392 }
2393
2394 /// Computes $\sec(\pi x)$, the secant of a [`Rational`] measured in half-turns, rounding the
2395 /// result to the specified precision and with the specified rounding mode and returning the
2396 /// result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned,
2397 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
2398 /// secant.
2399 ///
2400 /// This is `sec_with_period_rational` with a period of 2: see
2401 /// [`Float::sec_with_period_rational_prec_round`] for the error bounds, the special and
2402 /// closed-form cases, overflow, and the complexity, with $u = 2$.
2403 ///
2404 /// # Panics
2405 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2406 /// with the given precision.
2407 ///
2408 /// # Examples
2409 /// ```
2410 /// use malachite_base::rounding_modes::RoundingMode::*;
2411 /// use malachite_float::Float;
2412 /// use malachite_q::Rational;
2413 /// use std::cmp::Ordering::*;
2414 ///
2415 /// let (t, o) = Float::sec_pi_rational_prec_round(Rational::from_unsigneds(1u8, 7), 10, Floor);
2416 /// assert_eq!(t.to_string(), "1.1094");
2417 /// assert_eq!(o, Less);
2418 ///
2419 /// // a third of a half-turn is exactly 2
2420 /// let (t, o) = Float::sec_pi_rational_prec_round(Rational::from_unsigneds(1u8, 3), 10, Exact);
2421 /// assert_eq!(t.to_string(), "2.0000");
2422 /// assert_eq!(o, Equal);
2423 /// ```
2424 #[inline]
2425 #[allow(clippy::needless_pass_by_value)]
2426 pub fn sec_pi_rational_prec_round(
2427 x: Rational,
2428 prec: u64,
2429 rm: RoundingMode,
2430 ) -> (Self, Ordering) {
2431 Self::sec_with_period_rational_prec_round_ref(&x, 2, prec, rm)
2432 }
2433
2434 /// Computes $\sec(\pi x)$, the secant of a [`Rational`] measured in half-turns, rounding the
2435 /// result to the specified precision and with the specified rounding mode and returning the
2436 /// result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also
2437 /// returned, indicating whether the rounded secant is less than, equal to, or greater than the
2438 /// exact secant.
2439 ///
2440 /// This is `sec_with_period_rational` with a period of 2: see
2441 /// [`Float::sec_with_period_rational_prec_round_ref`] for the error bounds, the special and
2442 /// closed-form cases, overflow, and the complexity, with $u = 2$.
2443 ///
2444 /// # Panics
2445 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
2446 /// with the given precision.
2447 ///
2448 /// # Examples
2449 /// ```
2450 /// use malachite_base::rounding_modes::RoundingMode::*;
2451 /// use malachite_float::Float;
2452 /// use malachite_q::Rational;
2453 /// use std::cmp::Ordering::*;
2454 ///
2455 /// let (t, o) =
2456 /// Float::sec_pi_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 7), 10, Ceiling);
2457 /// assert_eq!(t.to_string(), "1.1113");
2458 /// assert_eq!(o, Greater);
2459 /// ```
2460 #[inline]
2461 pub fn sec_pi_rational_prec_round_ref(
2462 x: &Rational,
2463 prec: u64,
2464 rm: RoundingMode,
2465 ) -> (Self, Ordering) {
2466 Self::sec_with_period_rational_prec_round_ref(x, 2, prec, rm)
2467 }
2468
2469 /// Computes $\sec(\pi x)$, the secant of a [`Rational`] measured in half-turns, rounding the
2470 /// result to the nearest value of the specified precision and returning the result as a
2471 /// [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating
2472 /// whether the rounded secant is less than, equal to, or greater than the exact secant.
2473 ///
2474 /// This is `sec_with_period_rational` with a period of 2: see
2475 /// [`Float::sec_with_period_rational_prec`] for the error bounds, the special and closed-form
2476 /// cases, overflow, and the complexity, with $u = 2$.
2477 ///
2478 /// # Panics
2479 /// Panics if `prec` is zero.
2480 ///
2481 /// # Examples
2482 /// ```
2483 /// use malachite_float::Float;
2484 /// use malachite_q::Rational;
2485 /// use std::cmp::Ordering::*;
2486 ///
2487 /// let (t, o) = Float::sec_pi_rational_prec(Rational::from_unsigneds(1u8, 7), 53);
2488 /// assert_eq!(t.to_string(), "1.1099162641747424");
2489 /// assert_eq!(o, Greater);
2490 /// ```
2491 #[inline]
2492 #[allow(clippy::needless_pass_by_value)]
2493 pub fn sec_pi_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
2494 Self::sec_with_period_rational_prec_ref(&x, 2, prec)
2495 }
2496
2497 /// Computes $\sec(\pi x)$, the secant of a [`Rational`] measured in half-turns, rounding the
2498 /// result to the nearest value of the specified precision and returning the result as a
2499 /// [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also returned,
2500 /// indicating whether the rounded secant is less than, equal to, or greater than the exact
2501 /// secant.
2502 ///
2503 /// This is `sec_with_period_rational` with a period of 2: see
2504 /// [`Float::sec_with_period_rational_prec_ref`] for the error bounds, the special and
2505 /// closed-form cases, overflow, and the complexity, with $u = 2$.
2506 ///
2507 /// # Panics
2508 /// Panics if `prec` is zero.
2509 ///
2510 /// # Examples
2511 /// ```
2512 /// use malachite_float::Float;
2513 /// use malachite_q::Rational;
2514 /// use std::cmp::Ordering::*;
2515 ///
2516 /// let (t, o) = Float::sec_pi_rational_prec_ref(&Rational::from_unsigneds(1u8, 7), 53);
2517 /// assert_eq!(t.to_string(), "1.1099162641747424");
2518 /// assert_eq!(o, Greater);
2519 /// ```
2520 #[inline]
2521 pub fn sec_pi_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
2522 Self::sec_with_period_rational_prec_ref(x, 2, prec)
2523 }
2524}
2525
2526impl Sec for Float {
2527 type Output = Self;
2528
2529 /// Computes $\sec x$, the secant of a [`Float`], taking it by value.
2530 ///
2531 /// If the output has a precision, it is the precision of the input. If the secant is
2532 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
2533 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2534 /// rounding mode.
2535 ///
2536 /// $$
2537 /// f(x) = \sec x+\varepsilon.
2538 /// $$
2539 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
2540 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$, where $p$ is
2541 /// the precision of the input.
2542 ///
2543 /// Special cases:
2544 /// - $f(\text{NaN})=\text{NaN}$
2545 /// - $f(\pm\infty)=\text{NaN}$
2546 /// - $f(\pm0.0)=1.0$
2547 ///
2548 /// See the [`Float::sec_round`] documentation for information on overflow.
2549 ///
2550 /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::sec_round`]
2551 /// instead. If you want to specify the output precision, consider using [`Float::sec_prec`]. If
2552 /// you want both of these things, consider using [`Float::sec_prec_round`].
2553 ///
2554 /// # Worst-case complexity
2555 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
2556 ///
2557 /// $M(n, e) = O((n+e) \log (n+e))$
2558 ///
2559 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
2560 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
2561 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
2562 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
2563 /// e$ bits. Unlike most functions, `sec` therefore gets slower as the magnitude of its input
2564 /// grows, not just as the precision does.
2565 ///
2566 /// # Examples
2567 /// ```
2568 /// use malachite_base::num::arithmetic::traits::Sec;
2569 /// use malachite_base::num::basic::traits::*;
2570 /// use malachite_float::Float;
2571 ///
2572 /// assert!(Float::NAN.sec().is_nan());
2573 /// assert!(Float::INFINITY.sec().is_nan());
2574 /// assert!(Float::NEGATIVE_INFINITY.sec().is_nan());
2575 /// assert_eq!(Float::ZERO.sec().to_string(), "1.0");
2576 /// assert_eq!(Float::NEGATIVE_ZERO.sec().to_string(), "1.0");
2577 /// assert_eq!(
2578 /// Float::from_unsigned_prec(1u32, 100).0.sec().to_string(),
2579 /// "1.8508157176809256179117532413979"
2580 /// );
2581 /// assert_eq!(
2582 /// Float::from_unsigned_prec(100u32, 100).0.sec().to_string(),
2583 /// "1.1596638229046938325514044465873"
2584 /// );
2585 /// ```
2586 #[inline]
2587 fn sec(self) -> Self {
2588 let prec = self.significant_bits();
2589 self.sec_prec_round(prec, Nearest).0
2590 }
2591}
2592
2593impl Sec for &Float {
2594 type Output = Float;
2595
2596 /// Computes $\sec x$, the secant of a [`Float`], taking it by reference.
2597 ///
2598 /// If the output has a precision, it is the precision of the input. If the secant is
2599 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
2600 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2601 /// rounding mode.
2602 ///
2603 /// $$
2604 /// f(x) = \sec x+\varepsilon.
2605 /// $$
2606 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
2607 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$, where $p$ is
2608 /// the precision of the input.
2609 ///
2610 /// Special cases:
2611 /// - $f(\text{NaN})=\text{NaN}$
2612 /// - $f(\pm\infty)=\text{NaN}$
2613 /// - $f(\pm0.0)=1.0$
2614 ///
2615 /// See the [`Float::sec_round`] documentation for information on overflow.
2616 ///
2617 /// If you want to use a rounding mode other than `Nearest`, consider using
2618 /// [`Float::sec_round_ref`] instead. If you want to specify the output precision, consider
2619 /// using [`Float::sec_prec_ref`]. If you want both of these things, consider using
2620 /// [`Float::sec_prec_round_ref`].
2621 ///
2622 /// # Worst-case complexity
2623 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
2624 ///
2625 /// $M(n, e) = O((n+e) \log (n+e))$
2626 ///
2627 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
2628 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
2629 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
2630 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
2631 /// e$ bits. Unlike most functions, `sec` therefore gets slower as the magnitude of its input
2632 /// grows, not just as the precision does.
2633 ///
2634 /// # Examples
2635 /// ```
2636 /// use malachite_base::num::arithmetic::traits::Sec;
2637 /// use malachite_base::num::basic::traits::*;
2638 /// use malachite_float::Float;
2639 ///
2640 /// assert!(Float::NAN.sec().is_nan());
2641 /// assert!(Float::INFINITY.sec().is_nan());
2642 /// assert!(Float::NEGATIVE_INFINITY.sec().is_nan());
2643 /// assert_eq!(Float::ZERO.sec().to_string(), "1.0");
2644 /// assert_eq!(Float::NEGATIVE_ZERO.sec().to_string(), "1.0");
2645 /// assert_eq!(
2646 /// (&Float::from_unsigned_prec(1u32, 100).0).sec().to_string(),
2647 /// "1.8508157176809256179117532413979"
2648 /// );
2649 /// assert_eq!(
2650 /// (&Float::from_unsigned_prec(100u32, 100).0)
2651 /// .sec()
2652 /// .to_string(),
2653 /// "1.1596638229046938325514044465873"
2654 /// );
2655 /// ```
2656 #[inline]
2657 fn sec(self) -> Float {
2658 self.sec_prec_round_ref(self.significant_bits(), Nearest).0
2659 }
2660}
2661
2662impl SecAssign for Float {
2663 /// Computes $\sec x$, the secant of a [`Float`], in place.
2664 ///
2665 /// If the output has a precision, it is the precision of the input. If the secant is
2666 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
2667 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2668 /// rounding mode.
2669 ///
2670 /// $$
2671 /// x \gets \sec x+\varepsilon.
2672 /// $$
2673 /// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
2674 /// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$, where $p$ is
2675 /// the precision of the input.
2676 ///
2677 /// See the [`Float::sec`] documentation for information on special cases and overflow.
2678 ///
2679 /// If you want to use a rounding mode other than `Nearest`, consider using
2680 /// [`Float::sec_round_assign`] instead. If you want to specify the output precision, consider
2681 /// using [`Float::sec_prec_assign`]. If you want both of these things, consider using
2682 /// [`Float::sec_prec_round_assign`].
2683 ///
2684 /// # Worst-case complexity
2685 /// $T(n, e) = O(n (\log n)^3 \log\log n + (n+e) (\log (n+e))^2 \log\log (n+e))$
2686 ///
2687 /// $M(n, e) = O((n+e) \log (n+e))$
2688 ///
2689 /// where $T$ is time, $M$ is additional memory, $n$ is `self.significant_bits()`, and $e$ is
2690 /// the exponent of `self` (0 if `self` has no exponent or a negative one): the Taylor series at
2691 /// working precision $n$, summed by binary splitting for large $n$, costs the first term, and
2692 /// for $|x| \geq 4$ the argument is reduced modulo $2\pi$, which requires $\pi$ to about $n +
2693 /// e$ bits. Unlike most functions, `sec` therefore gets slower as the magnitude of its input
2694 /// grows, not just as the precision does.
2695 ///
2696 /// # Examples
2697 /// ```
2698 /// use malachite_base::num::arithmetic::traits::SecAssign;
2699 /// use malachite_base::num::basic::traits::*;
2700 /// use malachite_float::Float;
2701 ///
2702 /// let mut x = Float::NAN;
2703 /// x.sec_assign();
2704 /// assert!(x.is_nan());
2705 ///
2706 /// let mut x = Float::INFINITY;
2707 /// x.sec_assign();
2708 /// assert!(x.is_nan());
2709 ///
2710 /// let mut x = Float::NEGATIVE_INFINITY;
2711 /// x.sec_assign();
2712 /// assert!(x.is_nan());
2713 ///
2714 /// let mut x = Float::ZERO;
2715 /// x.sec_assign();
2716 /// assert_eq!(x.to_string(), "1.0");
2717 ///
2718 /// let mut x = Float::NEGATIVE_ZERO;
2719 /// x.sec_assign();
2720 /// assert_eq!(x.to_string(), "1.0");
2721 ///
2722 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
2723 /// x.sec_assign();
2724 /// assert_eq!(x.to_string(), "1.8508157176809256179117532413979");
2725 ///
2726 /// let mut x = Float::from_unsigned_prec(100u32, 100).0;
2727 /// x.sec_assign();
2728 /// assert_eq!(x.to_string(), "1.1596638229046938325514044465873");
2729 /// ```
2730 #[inline]
2731 fn sec_assign(&mut self) {
2732 let prec = self.significant_bits();
2733 self.sec_prec_round_assign(prec, Nearest);
2734 }
2735}
2736
2737/// Computes $\sec x$, the secant of a primitive float, correctly rounded. Neither the standard
2738/// library nor `libm` provides a secant.
2739///
2740/// $$
2741/// f(x) = \sec x+\varepsilon.
2742/// $$
2743/// - If $x$ is not finite, $\varepsilon$ may be ignored or assumed to be 0.
2744/// - If $x$ is finite, then $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$, where $p$ is the
2745/// precision of the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
2746///
2747/// Special cases:
2748/// - $f(\text{NaN})=\text{NaN}$
2749/// - $f(\pm\infty)=\text{NaN}$
2750/// - $f(\pm0.0)=1.0$
2751///
2752/// Overflow is not possible: no [`f32`] or [`f64`] is close enough to an odd multiple of $\pi/2$
2753/// for its secant to exceed the largest finite value (the largest secant of an [`f64`], like the
2754/// largest tangent, is below $2^{55}$). The result is never subnormal, since $|\sec x| \geq 1$.
2755///
2756/// # Worst-case complexity
2757/// Constant time and additional memory.
2758///
2759/// # Examples
2760/// ```
2761/// use malachite_base::num::basic::traits::NegativeInfinity;
2762/// use malachite_base::num::float::NiceFloat;
2763/// use malachite_float::float::arithmetic::sec::primitive_float_sec;
2764///
2765/// assert!(primitive_float_sec(f32::NAN).is_nan());
2766/// assert!(primitive_float_sec(f32::INFINITY).is_nan());
2767/// assert!(primitive_float_sec(f32::NEGATIVE_INFINITY).is_nan());
2768/// assert_eq!(NiceFloat(primitive_float_sec(0.0f32)), NiceFloat(1.0));
2769/// assert_eq!(NiceFloat(primitive_float_sec(-0.0f32)), NiceFloat(1.0));
2770/// assert_eq!(NiceFloat(primitive_float_sec(1.0f32)), NiceFloat(1.8508158));
2771/// assert_eq!(
2772/// NiceFloat(primitive_float_sec(1.0f64)),
2773/// NiceFloat(1.8508157176809257)
2774/// );
2775/// ```
2776#[inline]
2777#[allow(clippy::type_repetition_in_bounds)]
2778pub fn primitive_float_sec<T: PrimitiveFloat>(x: T) -> T
2779where
2780 Float: From<T> + PartialOrd<T>,
2781 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
2782{
2783 emulate_float_to_float_fn(Float::sec_prec, x)
2784}
2785
2786/// Computes $\sec x$, the secant of a [`Rational`], returning the result as a primitive float.
2787///
2788/// $$
2789/// f(x) = \sec x+\varepsilon,
2790/// $$
2791/// where $|\varepsilon| < 2^{\lfloor\log_2 |\sec x|\rfloor-p}$, and $p$ is the precision of the
2792/// output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
2793///
2794/// Special cases:
2795/// - $f(0)=1$
2796///
2797/// Overflow is possible: a [`Rational`] within about $2^{-129}$ of an odd multiple of $\pi/2$ has a
2798/// secant beyond the largest [`f32`], and one within about $2^{-1025}$ of one beyond the largest
2799/// [`f64`], and the result is then $\pm\infty$. Underflow is not possible, since $|\sec x| \geq 1$.
2800///
2801/// # Worst-case complexity
2802/// $T(m, e) = O((m+e) (\log (m+e))^2 \log\log (m+e))$
2803///
2804/// $M(m, e) = O((m+e) \log (m+e))$
2805///
2806/// where $T$ is time, $M$ is additional memory, $m$ is `x.significant_bits()`, and $e$ is
2807/// `x.floor_log_base_2_abs()` (taken as 0 when it is negative or $x = 0$): for $|x| \geq 3$ the
2808/// argument is reduced modulo $2\pi$, which needs $\pi$ to about $e$ bits.
2809///
2810/// # Examples
2811/// ```
2812/// use malachite_base::num::basic::traits::Zero;
2813/// use malachite_base::num::float::NiceFloat;
2814/// use malachite_float::float::arithmetic::sec::primitive_float_sec_rational;
2815/// use malachite_q::Rational;
2816///
2817/// assert_eq!(
2818/// NiceFloat(primitive_float_sec_rational::<f64>(&Rational::ZERO)),
2819/// NiceFloat(1.0)
2820/// );
2821/// assert_eq!(
2822/// NiceFloat(primitive_float_sec_rational::<f64>(
2823/// &Rational::from_unsigneds(1u8, 3)
2824/// )),
2825/// NiceFloat(1.058249271461442)
2826/// );
2827/// assert_eq!(
2828/// NiceFloat(primitive_float_sec_rational::<f32>(
2829/// &Rational::from_unsigneds(1u8, 3)
2830/// )),
2831/// NiceFloat(1.0582492)
2832/// );
2833/// assert_eq!(
2834/// NiceFloat(primitive_float_sec_rational::<f64>(&Rational::from(10000))),
2835/// NiceFloat(-1.050248765417841)
2836/// );
2837/// ```
2838#[inline]
2839#[allow(clippy::type_repetition_in_bounds)]
2840pub fn primitive_float_sec_rational<T: PrimitiveFloat>(x: &Rational) -> T
2841where
2842 Float: PartialOrd<T>,
2843 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
2844{
2845 emulate_rational_to_float_fn(Float::sec_rational_prec_ref, x)
2846}
2847
2848/// Computes $\sec(2\pi x/u)$, the secant of a primitive float measured in $u$ths of a turn (so that
2849/// `u = 360` is degrees).
2850///
2851/// $$
2852/// f(x,u) = \sec(2\pi x/u)+\varepsilon.
2853/// $$
2854/// - If $x$ is not finite, $u=0$, or $x/u$ is an odd multiple of $1/4$, $\varepsilon$ may be
2855/// ignored or assumed to be 0.
2856/// - Otherwise, $|\varepsilon| < 2^{\lfloor\log_2 |\sec(2\pi x/u)|\rfloor-p}$, where $p$ is the
2857/// precision of the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
2858///
2859/// Special cases:
2860/// - $f(\text{NaN},u)=\text{NaN}$
2861/// - $f(\pm\infty,u)=\text{NaN}$
2862/// - $f(x,0)=\text{NaN}$
2863/// - $f(\pm0.0,u)=1.0$
2864/// - If $x/u$ is an even multiple of $1/2$, the result is exactly $1$, and at an odd multiple
2865/// exactly $-1$.
2866/// - If $x/u$ is an odd multiple of $1/4$, the secant has a pole there, and the result is exactly
2867/// $\infty$: the cosine is $+0.0$ at every such point, and the secant is its reciprocal.
2868/// - If $x/u$ is an odd multiple of $1/8$, the result is $\pm\sqrt2$; if it is a multiple of $1/3$
2869/// or $1/6$ but not of $1/2$, the result is exactly $\pm2$; and if it is an odd multiple of
2870/// $1/12$, the result is $\pm2\sqrt3/3$.
2871///
2872/// Overflow happens only at a pole, where the result is exactly $\infty$: an [`f32`] or [`f64`]
2873/// whose fraction of a turn is not an odd multiple of $1/4$ is more than $2^{-66}$ of a turn away
2874/// from one, so its secant stays below $2^{64}$. Underflow is not possible, since $|\sec(2\pi x/u)|
2875/// \geq 1$.
2876///
2877/// # Worst-case complexity
2878/// Constant time and additional memory.
2879///
2880/// # Examples
2881/// ```
2882/// use malachite_base::num::basic::traits::NegativeInfinity;
2883/// use malachite_base::num::float::NiceFloat;
2884/// use malachite_float::float::arithmetic::sec::primitive_float_sec_with_period;
2885///
2886/// assert!(primitive_float_sec_with_period(f32::NAN, 360).is_nan());
2887/// assert!(primitive_float_sec_with_period(f32::INFINITY, 360).is_nan());
2888/// assert!(primitive_float_sec_with_period(f32::NEGATIVE_INFINITY, 360).is_nan());
2889/// assert!(primitive_float_sec_with_period(1.0f32, 0).is_nan());
2890/// assert_eq!(
2891/// NiceFloat(primitive_float_sec_with_period(-0.0f32, 360)),
2892/// NiceFloat(1.0)
2893/// );
2894/// // a quarter turn is a pole
2895/// assert_eq!(
2896/// NiceFloat(primitive_float_sec_with_period(90.0f32, 360)),
2897/// NiceFloat(f32::INFINITY)
2898/// );
2899/// // a half turn is exactly -1
2900/// assert_eq!(
2901/// NiceFloat(primitive_float_sec_with_period(180.0f32, 360)),
2902/// NiceFloat(-1.0)
2903/// );
2904/// // an eighth of a turn: sqrt(2)
2905/// assert_eq!(
2906/// NiceFloat(primitive_float_sec_with_period(45.0f32, 360)),
2907/// NiceFloat(core::f32::consts::SQRT_2)
2908/// );
2909/// // a twelfth of a turn: 2 sqrt(3)/3
2910/// assert_eq!(
2911/// NiceFloat(primitive_float_sec_with_period(30.0f64, 360)),
2912/// NiceFloat(1.1547005383792515)
2913/// );
2914/// assert_eq!(
2915/// NiceFloat(primitive_float_sec_with_period(1.0f32, 7)),
2916/// NiceFloat(1.6038755)
2917/// );
2918/// assert_eq!(
2919/// NiceFloat(primitive_float_sec_with_period(1.0f64, 7)),
2920/// NiceFloat(1.6038754716096766)
2921/// );
2922/// ```
2923#[inline]
2924#[allow(clippy::type_repetition_in_bounds)]
2925pub fn primitive_float_sec_with_period<T: PrimitiveFloat>(x: T, u: u64) -> T
2926where
2927 Float: From<T> + PartialOrd<T>,
2928 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
2929{
2930 emulate_float_to_float_fn(|x, prec| Float::sec_with_period_prec(x, u, prec), x)
2931}
2932
2933/// Computes $\sec(2\pi x/u)$, the secant of a [`Rational`] measured in $u$ths of a turn (so that `u
2934/// = 360` is degrees), returning the result as a primitive float.
2935///
2936/// $$
2937/// f(x,u) = \sec(2\pi x/u)+\varepsilon.
2938/// $$
2939/// - If $u=0$ or $x/u$ is an odd multiple of $1/4$, $\varepsilon$ may be ignored or assumed to be
2940/// 0.
2941/// - Otherwise, $|\varepsilon| < 2^{\lfloor\log_2 |\sec(2\pi x/u)|\rfloor-p}$, where $p$ is the
2942/// precision of the output (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
2943///
2944/// Special cases:
2945/// - $f(x,0)=\text{NaN}$
2946/// - $f(0,u)=1$
2947/// - If $x/u$ is an even multiple of $1/2$, the result is exactly $1$, and at an odd multiple
2948/// exactly $-1$.
2949/// - If $x/u$ is an odd multiple of $1/4$, the secant has a pole there, and the result is exactly
2950/// $\infty$: the cosine is $+0.0$ at every such point, and the secant is its reciprocal.
2951/// - If $x/u$ is an odd multiple of $1/8$, the result is $\pm\sqrt2$; if it is a multiple of $1/3$
2952/// or $1/6$ but not of $1/2$, the result is exactly $\pm2$; if it is an odd multiple of $1/12$,
2953/// the result is $\pm2\sqrt3/3$; and fifths and tenths give $\pm2\varphi$ or $\pm2(\varphi-1)$,
2954/// where $\varphi$ is the golden ratio.
2955///
2956/// Overflow is possible away from a pole too: a fraction of a turn within about $2^{-130}$ of an
2957/// odd multiple of $1/4$ has a secant beyond the largest [`f32`], and one within about $2^{-1026}$
2958/// of one beyond the largest [`f64`], and the result is then $\pm\infty$. Underflow is not
2959/// possible, since $|\sec(2\pi x/u)| \geq 1$.
2960///
2961/// # Worst-case complexity
2962/// $T(m) = O(m (\log m)^2 \log\log m)$
2963///
2964/// $M(m) = O(m \log m)$
2965///
2966/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`: the fraction of
2967/// a turn is reduced modulo 1 exactly, so the magnitude of $x$ does not drive the cost.
2968///
2969/// # Examples
2970/// ```
2971/// use malachite_base::num::basic::traits::Zero;
2972/// use malachite_base::num::float::NiceFloat;
2973/// use malachite_float::float::arithmetic::sec::primitive_float_sec_with_period_rational;
2974/// use malachite_q::Rational;
2975///
2976/// assert!(primitive_float_sec_with_period_rational::<f64>(&Rational::ZERO, 0).is_nan());
2977/// assert_eq!(
2978/// NiceFloat(primitive_float_sec_with_period_rational::<f64>(
2979/// &Rational::ZERO,
2980/// 360
2981/// )),
2982/// NiceFloat(1.0)
2983/// );
2984/// // a quarter turn is a pole
2985/// assert_eq!(
2986/// NiceFloat(primitive_float_sec_with_period_rational::<f64>(
2987/// &Rational::from_unsigneds(1u8, 4),
2988/// 1
2989/// )),
2990/// NiceFloat(f64::INFINITY)
2991/// );
2992/// // an eighth of a turn: sqrt(2)
2993/// assert_eq!(
2994/// NiceFloat(primitive_float_sec_with_period_rational::<f64>(
2995/// &Rational::from_unsigneds(1u8, 8),
2996/// 1
2997/// )),
2998/// NiceFloat(core::f64::consts::SQRT_2)
2999/// );
3000/// // a twelfth of a turn: 2 sqrt(3)/3
3001/// assert_eq!(
3002/// NiceFloat(primitive_float_sec_with_period_rational::<f64>(
3003/// &Rational::from_unsigneds(1u8, 12),
3004/// 1
3005/// )),
3006/// NiceFloat(1.1547005383792515)
3007/// );
3008/// assert_eq!(
3009/// NiceFloat(primitive_float_sec_with_period_rational::<f32>(
3010/// &Rational::from_unsigneds(1u8, 7),
3011/// 1
3012/// )),
3013/// NiceFloat(1.6038755)
3014/// );
3015/// assert_eq!(
3016/// NiceFloat(primitive_float_sec_with_period_rational::<f64>(
3017/// &Rational::from_unsigneds(1u8, 7),
3018/// 1
3019/// )),
3020/// NiceFloat(1.6038754716096766)
3021/// );
3022/// ```
3023#[inline]
3024#[allow(clippy::type_repetition_in_bounds)]
3025pub fn primitive_float_sec_with_period_rational<T: PrimitiveFloat>(x: &Rational, u: u64) -> T
3026where
3027 Float: PartialOrd<T>,
3028 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3029{
3030 emulate_rational_to_float_fn(
3031 |x, prec| Float::sec_with_period_rational_prec_ref(x, u, prec),
3032 x,
3033 )
3034}
3035
3036/// Computes $\sec(\pi x)$, the secant of a primitive float measured in half-turns.
3037///
3038/// This is `primitive_float_sec_with_period` with a period of 2: see
3039/// [`primitive_float_sec_with_period`] for the error bound and the special cases, with $u = 2$.
3040/// Half-integers are poles and give exactly $\infty$; even integers give exactly $1$ and odd ones
3041/// $-1$; odd multiples of $1/4$ give $\pm\sqrt2$; and multiples of $1/3$ give exactly $\pm2$.
3042///
3043/// # Worst-case complexity
3044/// Constant time and additional memory.
3045///
3046/// # Examples
3047/// ```
3048/// use malachite_base::num::float::NiceFloat;
3049/// use malachite_float::float::arithmetic::sec::primitive_float_sec_pi;
3050///
3051/// assert!(primitive_float_sec_pi(f32::NAN).is_nan());
3052/// // a half-integer is a pole
3053/// assert_eq!(
3054/// NiceFloat(primitive_float_sec_pi(0.5f32)),
3055/// NiceFloat(f32::INFINITY)
3056/// );
3057/// // an odd integer is exactly -1
3058/// assert_eq!(NiceFloat(primitive_float_sec_pi(1.0f64)), NiceFloat(-1.0));
3059/// // an odd multiple of a quarter: sqrt(2)
3060/// assert_eq!(
3061/// NiceFloat(primitive_float_sec_pi(0.25f32)),
3062/// NiceFloat(core::f32::consts::SQRT_2)
3063/// );
3064/// assert_eq!(
3065/// NiceFloat(primitive_float_sec_pi(0.1f32)),
3066/// NiceFloat(1.0514622)
3067/// );
3068/// assert_eq!(
3069/// NiceFloat(primitive_float_sec_pi(0.1f64)),
3070/// NiceFloat(1.0514622242382672)
3071/// );
3072/// ```
3073#[inline]
3074#[allow(clippy::type_repetition_in_bounds)]
3075pub fn primitive_float_sec_pi<T: PrimitiveFloat>(x: T) -> T
3076where
3077 Float: From<T> + PartialOrd<T>,
3078 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3079{
3080 primitive_float_sec_with_period(x, 2)
3081}
3082
3083/// Computes $\sec(\pi x)$, the secant of a [`Rational`] measured in half-turns, returning the
3084/// result as a primitive float.
3085///
3086/// This is `primitive_float_sec_with_period_rational` with a period of 2: see
3087/// [`primitive_float_sec_with_period_rational`] for the error bound, the special cases, and the
3088/// complexity, with $u = 2$.
3089///
3090/// # Worst-case complexity
3091/// $T(m) = O(m (\log m)^2 \log\log m)$
3092///
3093/// $M(m) = O(m \log m)$
3094///
3095/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`.
3096///
3097/// # Examples
3098/// ```
3099/// use malachite_base::num::basic::traits::OneHalf;
3100/// use malachite_base::num::float::NiceFloat;
3101/// use malachite_float::float::arithmetic::sec::primitive_float_sec_pi_rational;
3102/// use malachite_q::Rational;
3103///
3104/// // a half of a half-turn is a pole
3105/// assert_eq!(
3106/// NiceFloat(primitive_float_sec_pi_rational::<f64>(&Rational::ONE_HALF)),
3107/// NiceFloat(f64::INFINITY)
3108/// );
3109/// // a sixth of a half-turn: 2 sqrt(3)/3
3110/// assert_eq!(
3111/// NiceFloat(primitive_float_sec_pi_rational::<f64>(
3112/// &Rational::from_unsigneds(1u8, 6)
3113/// )),
3114/// NiceFloat(1.1547005383792515)
3115/// );
3116/// assert_eq!(
3117/// NiceFloat(primitive_float_sec_pi_rational::<f64>(
3118/// &Rational::from_unsigneds(1u8, 7)
3119/// )),
3120/// NiceFloat(1.1099162641747424)
3121/// );
3122/// ```
3123#[inline]
3124#[allow(clippy::type_repetition_in_bounds)]
3125pub fn primitive_float_sec_pi_rational<T: PrimitiveFloat>(x: &Rational) -> T
3126where
3127 Float: PartialOrd<T>,
3128 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3129{
3130 primitive_float_sec_with_period_rational(x, 2)
3131}