Skip to main content

malachite_float/float/arithmetic/
asech.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
10use crate::float::arithmetic::asinh::round_with_error;
11use crate::{Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
12use core::cmp::Ordering::{self, *};
13use malachite_base::fail_on_untested_path;
14use malachite_base::num::arithmetic::traits::{
15    Asech, AsechAssign, CeilingLogBase2, Ln, Ln1PlusX, Reciprocal, Sign, Sqrt,
16};
17use malachite_base::num::basic::floats::PrimitiveFloat;
18use malachite_base::num::basic::integers::PrimitiveInt;
19use malachite_base::num::basic::traits::{
20    Infinity as InfinityTrait, NaN as NaNTrait, One, Zero as ZeroTrait,
21};
22use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
23use malachite_base::num::logic::traits::SignificantBits;
24use malachite_base::rounding_modes::RoundingMode::{self, *};
25use malachite_nz::platform::Limb;
26use malachite_q::Rational;
27
28// Computes asech(x) = acosh(1/x) = ln((1 + sqrt(1 - x^2))/x) for a `Float` x with 0 < x < 1. MPFR
29// has no asech, so this is Malachite's own algorithm. Computing 1/x first would be ill-conditioned
30// near x = 1, where acosh has an infinite derivative, and would overflow for the smallest `Float`s,
31// so the two halves of the domain are handled differently, each without cancellation:
32//
33// - For 1/2 <= x < 1, let t = 1 - x, which is exact (Sterbenz). Then 1 - x^2 = t(1 + x), and
34//   asech(x) = ln(1 + u) with u = (t + sqrt(t(1 + x)))/x, all of whose terms are positive. Each of
35//   the five operations forming u has a relative error of at most 2^-wp, so u's is below 4 * 2^-wp
36//   (the square root halves the error of its argument). Since ln(1+u) >= u/(1+u), that moves
37//   ln(1+u) by less than 4.02 * 2^-wp ln(1+u), about 4 ulps, and its own rounding adds 1/2 ulp:
38//   under 2^3 ulps.
39// - For 0 < x < 1/2, asech(x) = ln(1 + s) - ln(x) with s = sqrt((1 - x)(1 + x)) in (0.86, 1]. Both
40//   terms are positive, ln(1 + s) < 0.7 < -ln(x), and the sum exceeds 1.3, so its ulp is at least
41//   2^(1-wp). s has relative error below 2.5 * 2^-wp, which moves ln(1 + s) by less than 1.3 *
42//   2^-wp; with the three roundings (of ln(1 + s), of ln(x), and of the sum), each at most half an
43//   ulp of the sum, the error is below 3 ulps: under 2^3 ulps again.
44//
45// If t(1 + x) underflows, which needs an x with a precision above 2^30, sqrt(t) sqrt(1 + x) is used
46// instead; its relative error is below 2^-wp more, which the bound absorbs.
47fn asech_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
48    assert_ne!(rm, Exact, "Inexact asech");
49    let near_one = x.get_exponent().unwrap() == 0; // 1/2 <= x < 1
50    // t = 1 - x, exact at x's precision for 1/2 <= x < 1
51    let t = near_one.then(|| {
52        let (t, o) = Float::ONE.sub_prec_ref_ref(x, x.get_prec().unwrap());
53        assert_eq!(o, Equal);
54        t
55    });
56    let exp_x = i64::from(x.get_exponent().unwrap());
57    let mut working_prec = prec + prec.ceiling_log_base_2() + 10;
58    let mut increment = Limb::WIDTH;
59    loop {
60        let t = if let Some(t) = &t {
61            // 1 + x
62            let one_plus_x = x.add_prec_ref_val(Float::ONE, working_prec).0;
63            let s = if t.get_exponent().unwrap() > const { Float::MIN_EXPONENT + 1 } {
64                // sqrt(t(1 + x))
65                t.mul_prec_ref_val(one_plus_x, working_prec).0.sqrt()
66            } else {
67                fail_on_untested_path("asech_prec_round_normal_ref, t(1 + x) may underflow");
68                t.sqrt_prec_ref(working_prec).0 * one_plus_x.sqrt()
69            };
70            // ln(1 + (t + s)/x)
71            s.add_prec_val_ref(t, working_prec)
72                .0
73                .div_prec_val_ref(x, working_prec)
74                .0
75                .ln_1_plus_x()
76        } else if exp_x << 1 <= 1 - i64::exact_from(working_prec) {
77            // x^2 < 2^(1-wp), so ln(1 + sqrt(1 - x^2)) = ln 2 - c with 0 < c < x^2, which is at
78            // most 1 ulp of the sum (whose ulp is at least 2^(1-wp)): with the three roundings the
79            // error stays below 2.5 ulps, under 2^3 ulps
80            Float::ln_2_prec(working_prec).0 - x.ln_prec_ref(working_prec).0
81        } else {
82            // s = sqrt((1 - x)(1 + x))
83            let s = (Float::ONE.sub_prec_val_ref(x, working_prec).0
84                * x.add_prec_ref_val(Float::ONE, working_prec).0)
85                .sqrt();
86            // ln(1 + s) - ln(x)
87            (s + Float::ONE).ln() - x.ln_prec_ref(working_prec).0
88        };
89        if let Some(result) = round_with_error(t, working_prec, 3, prec, rm) {
90            return result;
91        }
92        working_prec += increment;
93        increment = working_prec >> 1;
94    }
95}
96
97impl Float {
98    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
99    /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
100    /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded inverse
101    /// hyperbolic secant is less than, equal to, or greater than the exact inverse hyperbolic
102    /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
103    /// a `NaN` it also returns `Equal`.
104    ///
105    /// See [`RoundingMode`] for a description of the possible rounding modes.
106    ///
107    /// $$
108    /// f(x,p,m) = \operatorname{asech} x+\varepsilon.
109    /// $$
110    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
111    ///   assumed to be 0.
112    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
113    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$.
114    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
115    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$.
116    ///
117    /// If the output has a precision, it is `prec`.
118    ///
119    /// Special cases:
120    /// - $f(\text{NaN},p,m)=\text{NaN}$
121    /// - $f(\pm\infty,p,m)=\text{NaN}$
122    /// - $f(\pm0.0,p,m)=\infty$
123    /// - $f(1,p,m)=0.0$
124    /// - $f(x,p,m)=\text{NaN}$ if $x<0$ or $x>1$
125    ///
126    /// The result never overflows, since $\operatorname{asech} x < \ln(2/x) < 2^{30}$ for every
127    /// positive [`Float`] $x$. It underflows only for an $x$ within $2^{-2^{31}}$ of 1, since
128    /// $\operatorname{asech}(1-t) > \sqrt t$, and such an $x$ needs a precision above $2^{31}$.
129    ///
130    /// If you know you'll be using `Nearest`, consider using [`Float::asech_prec`] instead. If you
131    /// know that your target precision is the precision of the input, consider using
132    /// [`Float::asech_round`] instead. If both of these things are true, consider using
133    /// [`Float::asech`] instead.
134    ///
135    /// # Worst-case complexity
136    /// $T(n) = O(n (\log n)^2 \log\log n)$
137    ///
138    /// $M(n) = O(n \log n)$
139    ///
140    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
141    /// self.significant_bits())`.
142    ///
143    /// # Panics
144    /// Panics if `rm` is `Exact` and `self` is finite, nonzero, and less than 1 in absolute value,
145    /// since the inverse hyperbolic secant of such a [`Float`] is never exactly representable, or
146    /// if `prec` is zero.
147    ///
148    /// # Examples
149    /// ```
150    /// use malachite_base::rounding_modes::RoundingMode::*;
151    /// use malachite_float::Float;
152    /// use std::cmp::Ordering::*;
153    ///
154    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round(5, Floor);
155    /// assert_eq!(c.to_string(), "1.31");
156    /// assert_eq!(o, Less);
157    ///
158    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round(5, Ceiling);
159    /// assert_eq!(c.to_string(), "1.38");
160    /// assert_eq!(o, Greater);
161    ///
162    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round(5, Nearest);
163    /// assert_eq!(c.to_string(), "1.31");
164    /// assert_eq!(o, Less);
165    ///
166    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round(20, Floor);
167    /// assert_eq!(c.to_string(), "1.3169575");
168    /// assert_eq!(o, Less);
169    ///
170    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round(20, Ceiling);
171    /// assert_eq!(c.to_string(), "1.3169594");
172    /// assert_eq!(o, Greater);
173    ///
174    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round(20, Nearest);
175    /// assert_eq!(c.to_string(), "1.3169575");
176    /// assert_eq!(o, Less);
177    /// ```
178    #[inline]
179    pub fn asech_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
180        self.asech_prec_round_ref(prec, rm)
181    }
182
183    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
184    /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
185    /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded inverse
186    /// hyperbolic secant is less than, equal to, or greater than the exact inverse hyperbolic
187    /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
188    /// a `NaN` it also returns `Equal`.
189    ///
190    /// See [`RoundingMode`] for a description of the possible rounding modes.
191    ///
192    /// $$
193    /// f(x,p,m) = \operatorname{asech} x+\varepsilon.
194    /// $$
195    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
196    ///   assumed to be 0.
197    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
198    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$.
199    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
200    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$.
201    ///
202    /// If the output has a precision, it is `prec`.
203    ///
204    /// Special cases:
205    /// - $f(\text{NaN},p,m)=\text{NaN}$
206    /// - $f(\pm\infty,p,m)=\text{NaN}$
207    /// - $f(\pm0.0,p,m)=\infty$
208    /// - $f(1,p,m)=0.0$
209    /// - $f(x,p,m)=\text{NaN}$ if $x<0$ or $x>1$
210    ///
211    /// The result never overflows, since $\operatorname{asech} x < \ln(2/x) < 2^{30}$ for every
212    /// positive [`Float`] $x$. It underflows only for an $x$ within $2^{-2^{31}}$ of 1, since
213    /// $\operatorname{asech}(1-t) > \sqrt t$, and such an $x$ needs a precision above $2^{31}$.
214    ///
215    /// If you know you'll be using `Nearest`, consider using [`Float::asech_prec_ref`] instead. If
216    /// you know that your target precision is the precision of the input, consider using
217    /// [`Float::asech_round_ref`] instead. If both of these things are true, consider using
218    /// `(&Float).asech()` instead.
219    ///
220    /// # Worst-case complexity
221    /// $T(n) = O(n (\log n)^2 \log\log n)$
222    ///
223    /// $M(n) = O(n \log n)$
224    ///
225    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
226    /// self.significant_bits())`.
227    ///
228    /// # Panics
229    /// Panics if `rm` is `Exact` and `self` is finite, nonzero, and less than 1 in absolute value,
230    /// since the inverse hyperbolic secant of such a [`Float`] is never exactly representable, or
231    /// if `prec` is zero.
232    ///
233    /// # Examples
234    /// ```
235    /// use malachite_base::rounding_modes::RoundingMode::*;
236    /// use malachite_float::Float;
237    /// use std::cmp::Ordering::*;
238    ///
239    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round_ref(5, Floor);
240    /// assert_eq!(c.to_string(), "1.31");
241    /// assert_eq!(o, Less);
242    ///
243    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round_ref(5, Ceiling);
244    /// assert_eq!(c.to_string(), "1.38");
245    /// assert_eq!(o, Greater);
246    ///
247    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round_ref(5, Nearest);
248    /// assert_eq!(c.to_string(), "1.31");
249    /// assert_eq!(o, Less);
250    ///
251    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round_ref(20, Floor);
252    /// assert_eq!(c.to_string(), "1.3169575");
253    /// assert_eq!(o, Less);
254    ///
255    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round_ref(20, Ceiling);
256    /// assert_eq!(c.to_string(), "1.3169594");
257    /// assert_eq!(o, Greater);
258    ///
259    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_round_ref(20, Nearest);
260    /// assert_eq!(c.to_string(), "1.3169575");
261    /// assert_eq!(o, Less);
262    /// ```
263    pub fn asech_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
264        assert_ne!(prec, 0);
265        match &self.0 {
266            // asech is NaN for NaN, both infinities, and everything below 0
267            NaN | Infinity { .. } | Finite { sign: false, .. } => (Self::NAN, Equal),
268            // asech(+/-0) = +Inf, the limit from above; like ln, asech treats -0 as 0
269            Zero { .. } => (Self::INFINITY, Equal),
270            Finite { .. } => match self.partial_cmp(&1u32).unwrap() {
271                Less => asech_prec_round_normal_ref(self, prec, rm),
272                // asech(1) = +0
273                Equal => (Self::ZERO, Equal),
274                // asech is NaN above 1
275                Greater => (Self::NAN, Equal),
276            },
277        }
278    }
279
280    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
281    /// the result to the nearest value of the specified precision. The [`Float`] is taken by value.
282    /// An [`Ordering`] is also returned, indicating whether the rounded inverse hyperbolic secant
283    /// is less than, equal to, or greater than the exact inverse hyperbolic secant. Although `NaN`s
284    /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
285    /// `Equal`.
286    ///
287    /// If the inverse hyperbolic secant is equidistant from two [`Float`]s with the specified
288    /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
289    /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
290    ///
291    /// $$
292    /// f(x,p) = \operatorname{asech} x+\varepsilon.
293    /// $$
294    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
295    ///   assumed to be 0.
296    /// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
297    ///   \operatorname{asech} x\rfloor-p}$.
298    ///
299    /// If the output has a precision, it is `prec`.
300    ///
301    /// Special cases:
302    /// - $f(\text{NaN},p)=\text{NaN}$
303    /// - $f(\pm\infty,p)=\text{NaN}$
304    /// - $f(\pm0.0,p)=\infty$
305    /// - $f(1,p)=0.0$
306    /// - $f(x,p)=\text{NaN}$ if $x<0$ or $x>1$
307    ///
308    /// The result never overflows, since $\operatorname{asech} x < \ln(2/x) < 2^{30}$ for every
309    /// positive [`Float`] $x$. It underflows only for an $x$ within $2^{-2^{31}}$ of 1, since
310    /// $\operatorname{asech}(1-t) > \sqrt t$, and such an $x$ needs a precision above $2^{31}$.
311    ///
312    /// If you want to use a rounding mode other than `Nearest`, consider using
313    /// [`Float::asech_prec_round`] instead. If you know that your target precision is the precision
314    /// of the input, consider using [`Float::asech`] instead.
315    ///
316    /// # Worst-case complexity
317    /// $T(n) = O(n (\log n)^2 \log\log n)$
318    ///
319    /// $M(n) = O(n \log n)$
320    ///
321    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
322    /// self.significant_bits())`.
323    ///
324    /// # Panics
325    /// Panics if `prec` is zero.
326    ///
327    /// # Examples
328    /// ```
329    /// use malachite_float::Float;
330    /// use std::cmp::Ordering::*;
331    ///
332    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec(5);
333    /// assert_eq!(c.to_string(), "1.31");
334    /// assert_eq!(o, Less);
335    ///
336    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec(20);
337    /// assert_eq!(c.to_string(), "1.3169575");
338    /// assert_eq!(o, Less);
339    /// ```
340    #[inline]
341    pub fn asech_prec(self, prec: u64) -> (Self, Ordering) {
342        self.asech_prec_round(prec, Nearest)
343    }
344
345    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
346    /// the result to the nearest value of the specified precision. The [`Float`] is taken by
347    /// reference. An [`Ordering`] is also returned, indicating whether the rounded inverse
348    /// hyperbolic secant is less than, equal to, or greater than the exact inverse hyperbolic
349    /// secant. Although `NaN`s are not comparable to any [`Float`], whenever this function returns
350    /// a `NaN` it also returns `Equal`.
351    ///
352    /// If the inverse hyperbolic secant is equidistant from two [`Float`]s with the specified
353    /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
354    /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
355    ///
356    /// $$
357    /// f(x,p) = \operatorname{asech} x+\varepsilon.
358    /// $$
359    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
360    ///   assumed to be 0.
361    /// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
362    ///   \operatorname{asech} x\rfloor-p}$.
363    ///
364    /// If the output has a precision, it is `prec`.
365    ///
366    /// Special cases:
367    /// - $f(\text{NaN},p)=\text{NaN}$
368    /// - $f(\pm\infty,p)=\text{NaN}$
369    /// - $f(\pm0.0,p)=\infty$
370    /// - $f(1,p)=0.0$
371    /// - $f(x,p)=\text{NaN}$ if $x<0$ or $x>1$
372    ///
373    /// The result never overflows, since $\operatorname{asech} x < \ln(2/x) < 2^{30}$ for every
374    /// positive [`Float`] $x$. It underflows only for an $x$ within $2^{-2^{31}}$ of 1, since
375    /// $\operatorname{asech}(1-t) > \sqrt t$, and such an $x$ needs a precision above $2^{31}$.
376    ///
377    /// If you want to use a rounding mode other than `Nearest`, consider using
378    /// [`Float::asech_prec_round_ref`] instead. If you know that your target precision is the
379    /// precision of the input, consider using `(&Float).asech()` instead.
380    ///
381    /// # Worst-case complexity
382    /// $T(n) = O(n (\log n)^2 \log\log n)$
383    ///
384    /// $M(n) = O(n \log n)$
385    ///
386    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
387    /// self.significant_bits())`.
388    ///
389    /// # Panics
390    /// Panics if `prec` is zero.
391    ///
392    /// # Examples
393    /// ```
394    /// use malachite_float::Float;
395    /// use std::cmp::Ordering::*;
396    ///
397    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_ref(5);
398    /// assert_eq!(c.to_string(), "1.31");
399    /// assert_eq!(o, Less);
400    ///
401    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_prec_ref(20);
402    /// assert_eq!(c.to_string(), "1.3169575");
403    /// assert_eq!(o, Less);
404    /// ```
405    #[inline]
406    pub fn asech_prec_ref(&self, prec: u64) -> (Self, Ordering) {
407        self.asech_prec_round_ref(prec, Nearest)
408    }
409
410    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
411    /// the result with the specified rounding mode. The [`Float`] is taken by value. An
412    /// [`Ordering`] is also returned, indicating whether the rounded inverse hyperbolic secant is
413    /// less than, equal to, or greater than the exact inverse hyperbolic secant. Although `NaN`s
414    /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
415    /// `Equal`.
416    ///
417    /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
418    /// description of the possible rounding modes.
419    ///
420    /// $$
421    /// f(x,m) = \operatorname{asech} x+\varepsilon.
422    /// $$
423    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
424    ///   assumed to be 0.
425    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
426    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$, where $p$ is the
427    ///   precision of the input.
428    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
429    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$, where $p$ is the
430    ///   precision of the input.
431    ///
432    /// If the output has a precision, it is the precision of the input.
433    ///
434    /// Special cases:
435    /// - $f(\text{NaN},m)=\text{NaN}$
436    /// - $f(\pm\infty,m)=\text{NaN}$
437    /// - $f(\pm0.0,m)=\infty$
438    /// - $f(1,m)=0.0$
439    /// - $f(x,m)=\text{NaN}$ if $x<0$ or $x>1$
440    ///
441    /// The result never overflows, since $\operatorname{asech} x < \ln(2/x) < 2^{30}$ for every
442    /// positive [`Float`] $x$. It underflows only for an $x$ within $2^{-2^{31}}$ of 1, since
443    /// $\operatorname{asech}(1-t) > \sqrt t$, and such an $x$ needs a precision above $2^{31}$.
444    ///
445    /// If you want to specify an output precision, consider using [`Float::asech_prec_round`]
446    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
447    /// [`Float::asech`] instead.
448    ///
449    /// # Worst-case complexity
450    /// $T(n) = O(n (\log n)^2 \log\log n)$
451    ///
452    /// $M(n) = O(n \log n)$
453    ///
454    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
455    ///
456    /// # Panics
457    /// Panics if `rm` is `Exact` and `self` is finite, nonzero, and less than 1 in absolute value,
458    /// since the inverse hyperbolic secant of such a [`Float`] is never exactly representable.
459    ///
460    /// # Examples
461    /// ```
462    /// use malachite_base::rounding_modes::RoundingMode::*;
463    /// use malachite_float::Float;
464    /// use std::cmp::Ordering::*;
465    ///
466    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_round(Floor);
467    /// assert_eq!(c.to_string(), "1.3169578969248167086250463473073");
468    /// assert_eq!(o, Less);
469    ///
470    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_round(Ceiling);
471    /// assert_eq!(c.to_string(), "1.3169578969248167086250463473089");
472    /// assert_eq!(o, Greater);
473    ///
474    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_round(Nearest);
475    /// assert_eq!(c.to_string(), "1.3169578969248167086250463473073");
476    /// assert_eq!(o, Less);
477    /// ```
478    #[inline]
479    pub fn asech_round(self, rm: RoundingMode) -> (Self, Ordering) {
480        let prec = self.significant_bits();
481        self.asech_prec_round(prec, rm)
482    }
483
484    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
485    /// the result with the specified rounding mode. The [`Float`] is taken by reference. An
486    /// [`Ordering`] is also returned, indicating whether the rounded inverse hyperbolic secant is
487    /// less than, equal to, or greater than the exact inverse hyperbolic secant. Although `NaN`s
488    /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
489    /// `Equal`.
490    ///
491    /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
492    /// description of the possible rounding modes.
493    ///
494    /// $$
495    /// f(x,m) = \operatorname{asech} x+\varepsilon.
496    /// $$
497    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
498    ///   assumed to be 0.
499    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
500    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$, where $p$ is the
501    ///   precision of the input.
502    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
503    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$, where $p$ is the
504    ///   precision of the input.
505    ///
506    /// If the output has a precision, it is the precision of the input.
507    ///
508    /// Special cases:
509    /// - $f(\text{NaN},m)=\text{NaN}$
510    /// - $f(\pm\infty,m)=\text{NaN}$
511    /// - $f(\pm0.0,m)=\infty$
512    /// - $f(1,m)=0.0$
513    /// - $f(x,m)=\text{NaN}$ if $x<0$ or $x>1$
514    ///
515    /// The result never overflows, since $\operatorname{asech} x < \ln(2/x) < 2^{30}$ for every
516    /// positive [`Float`] $x$. It underflows only for an $x$ within $2^{-2^{31}}$ of 1, since
517    /// $\operatorname{asech}(1-t) > \sqrt t$, and such an $x$ needs a precision above $2^{31}$.
518    ///
519    /// If you want to specify an output precision, consider using [`Float::asech_prec_round_ref`]
520    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
521    /// `(&Float).asech()` instead.
522    ///
523    /// # Worst-case complexity
524    /// $T(n) = O(n (\log n)^2 \log\log n)$
525    ///
526    /// $M(n) = O(n \log n)$
527    ///
528    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
529    ///
530    /// # Panics
531    /// Panics if `rm` is `Exact` and `self` is finite, nonzero, and less than 1 in absolute value,
532    /// since the inverse hyperbolic secant of such a [`Float`] is never exactly representable.
533    ///
534    /// # Examples
535    /// ```
536    /// use malachite_base::rounding_modes::RoundingMode::*;
537    /// use malachite_float::Float;
538    /// use std::cmp::Ordering::*;
539    ///
540    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_round_ref(Floor);
541    /// assert_eq!(c.to_string(), "1.3169578969248167086250463473073");
542    /// assert_eq!(o, Less);
543    ///
544    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_round_ref(Ceiling);
545    /// assert_eq!(c.to_string(), "1.3169578969248167086250463473089");
546    /// assert_eq!(o, Greater);
547    ///
548    /// let (c, o) = (Float::one_prec(100) >> 1u32).asech_round_ref(Nearest);
549    /// assert_eq!(c.to_string(), "1.3169578969248167086250463473073");
550    /// assert_eq!(o, Less);
551    /// ```
552    #[inline]
553    pub fn asech_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
554        self.asech_prec_round_ref(self.significant_bits(), rm)
555    }
556
557    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
558    /// the result to the specified precision and with the specified rounding mode. The [`Float`] is
559    /// replaced by the result, and an [`Ordering`] is returned, indicating whether the rounded
560    /// inverse hyperbolic secant is less than, equal to, or greater than the exact inverse
561    /// hyperbolic secant. Although `NaN`s are not comparable to any [`Float`], whenever this
562    /// function sets a `NaN` it also returns `Equal`.
563    ///
564    /// See [`RoundingMode`] for a description of the possible rounding modes.
565    ///
566    /// $$
567    /// x \gets \operatorname{asech} x+\varepsilon.
568    /// $$
569    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
570    ///   assumed to be 0.
571    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
572    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$.
573    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
574    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$.
575    ///
576    /// If the output has a precision, it is `prec`.
577    ///
578    /// See the [`Float::asech_prec_round`] documentation for information on special cases,
579    /// overflow, and underflow.
580    ///
581    /// If you know you'll be using `Nearest`, consider using [`Float::asech_prec_assign`] instead.
582    /// If you know that your target precision is the precision of the input, consider using
583    /// [`Float::asech_round_assign`] instead. If both of these things are true, consider using
584    /// [`Float::asech_assign`] instead.
585    ///
586    /// # Worst-case complexity
587    /// $T(n) = O(n (\log n)^2 \log\log n)$
588    ///
589    /// $M(n) = O(n \log n)$
590    ///
591    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
592    /// self.significant_bits())`.
593    ///
594    /// # Panics
595    /// Panics if `rm` is `Exact` and `self` is finite, nonzero, and less than 1 in absolute value,
596    /// since the inverse hyperbolic secant of such a [`Float`] is never exactly representable, or
597    /// if `prec` is zero.
598    ///
599    /// # Examples
600    /// ```
601    /// use malachite_base::rounding_modes::RoundingMode::*;
602    /// use malachite_float::Float;
603    /// use std::cmp::Ordering::*;
604    ///
605    /// let mut x = Float::one_prec(100) >> 1u32;
606    /// assert_eq!(x.asech_prec_round_assign(5, Floor), Less);
607    /// assert_eq!(x.to_string(), "1.31");
608    ///
609    /// let mut x = Float::one_prec(100) >> 1u32;
610    /// assert_eq!(x.asech_prec_round_assign(5, Ceiling), Greater);
611    /// assert_eq!(x.to_string(), "1.38");
612    ///
613    /// let mut x = Float::one_prec(100) >> 1u32;
614    /// assert_eq!(x.asech_prec_round_assign(5, Nearest), Less);
615    /// assert_eq!(x.to_string(), "1.31");
616    ///
617    /// let mut x = Float::one_prec(100) >> 1u32;
618    /// assert_eq!(x.asech_prec_round_assign(20, Floor), Less);
619    /// assert_eq!(x.to_string(), "1.3169575");
620    ///
621    /// let mut x = Float::one_prec(100) >> 1u32;
622    /// assert_eq!(x.asech_prec_round_assign(20, Ceiling), Greater);
623    /// assert_eq!(x.to_string(), "1.3169594");
624    ///
625    /// let mut x = Float::one_prec(100) >> 1u32;
626    /// assert_eq!(x.asech_prec_round_assign(20, Nearest), Less);
627    /// assert_eq!(x.to_string(), "1.3169575");
628    /// ```
629    #[inline]
630    pub fn asech_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
631        let o;
632        (*self, o) = self.asech_prec_round_ref(prec, rm);
633        o
634    }
635
636    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
637    /// the result to the nearest value of the specified precision. The [`Float`] is replaced by the
638    /// result, and an [`Ordering`] is returned, indicating whether the rounded inverse hyperbolic
639    /// secant is less than, equal to, or greater than the exact inverse hyperbolic secant. Although
640    /// `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it also
641    /// returns `Equal`.
642    ///
643    /// If the inverse hyperbolic secant is equidistant from two [`Float`]s with the specified
644    /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
645    /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
646    ///
647    /// $$
648    /// x \gets \operatorname{asech} x+\varepsilon.
649    /// $$
650    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
651    ///   assumed to be 0.
652    /// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
653    ///   \operatorname{asech} x\rfloor-p}$.
654    ///
655    /// If the output has a precision, it is `prec`.
656    ///
657    /// See the [`Float::asech_prec`] documentation for information on special cases, overflow, and
658    /// underflow.
659    ///
660    /// If you want to use a rounding mode other than `Nearest`, consider using
661    /// [`Float::asech_prec_round_assign`] instead. If you know that your target precision is the
662    /// precision of the input, consider using [`Float::asech_assign`] instead.
663    ///
664    /// # Worst-case complexity
665    /// $T(n) = O(n (\log n)^2 \log\log n)$
666    ///
667    /// $M(n) = O(n \log n)$
668    ///
669    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(prec,
670    /// self.significant_bits())`.
671    ///
672    /// # Panics
673    /// Panics if `prec` is zero.
674    ///
675    /// # Examples
676    /// ```
677    /// use malachite_float::Float;
678    /// use std::cmp::Ordering::*;
679    ///
680    /// let mut x = Float::one_prec(100) >> 1u32;
681    /// assert_eq!(x.asech_prec_assign(5), Less);
682    /// assert_eq!(x.to_string(), "1.31");
683    ///
684    /// let mut x = Float::one_prec(100) >> 1u32;
685    /// assert_eq!(x.asech_prec_assign(20), Less);
686    /// assert_eq!(x.to_string(), "1.3169575");
687    /// ```
688    #[inline]
689    pub fn asech_prec_assign(&mut self, prec: u64) -> Ordering {
690        self.asech_prec_round_assign(prec, Nearest)
691    }
692
693    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], rounding
694    /// the result with the specified rounding mode. The [`Float`] is replaced by the result, and an
695    /// [`Ordering`] is returned, indicating whether the rounded inverse hyperbolic secant is less
696    /// than, equal to, or greater than the exact inverse hyperbolic secant. Although `NaN`s are not
697    /// comparable to any [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
698    ///
699    /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
700    /// description of the possible rounding modes.
701    ///
702    /// $$
703    /// x \gets \operatorname{asech} x+\varepsilon.
704    /// $$
705    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
706    ///   assumed to be 0.
707    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
708    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$, where $p$ is the
709    ///   precision of the input.
710    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
711    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$, where $p$ is the
712    ///   precision of the input.
713    ///
714    /// If the output has a precision, it is the precision of the input.
715    ///
716    /// See the [`Float::asech_round`] documentation for information on special cases, overflow, and
717    /// underflow.
718    ///
719    /// If you want to specify an output precision, consider using
720    /// [`Float::asech_prec_round_assign`] instead. If you know you'll be using the `Nearest`
721    /// rounding mode, consider using [`Float::asech_assign`] instead.
722    ///
723    /// # Worst-case complexity
724    /// $T(n) = O(n (\log n)^2 \log\log n)$
725    ///
726    /// $M(n) = O(n \log n)$
727    ///
728    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
729    ///
730    /// # Panics
731    /// Panics if `rm` is `Exact` and `self` is finite, nonzero, and less than 1 in absolute value,
732    /// since the inverse hyperbolic secant of such a [`Float`] is never exactly representable.
733    ///
734    /// # Examples
735    /// ```
736    /// use malachite_base::rounding_modes::RoundingMode::*;
737    /// use malachite_float::Float;
738    /// use std::cmp::Ordering::*;
739    ///
740    /// let mut x = Float::one_prec(100) >> 1u32;
741    /// assert_eq!(x.asech_round_assign(Floor), Less);
742    /// assert_eq!(x.to_string(), "1.3169578969248167086250463473073");
743    ///
744    /// let mut x = Float::one_prec(100) >> 1u32;
745    /// assert_eq!(x.asech_round_assign(Ceiling), Greater);
746    /// assert_eq!(x.to_string(), "1.3169578969248167086250463473089");
747    ///
748    /// let mut x = Float::one_prec(100) >> 1u32;
749    /// assert_eq!(x.asech_round_assign(Nearest), Less);
750    /// assert_eq!(x.to_string(), "1.3169578969248167086250463473073");
751    /// ```
752    #[inline]
753    pub fn asech_round_assign(&mut self, rm: RoundingMode) -> Ordering {
754        let prec = self.significant_bits();
755        self.asech_prec_round_assign(prec, rm)
756    }
757
758    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Rational`], rounding
759    /// the result to the specified precision and with the specified rounding mode and returning the
760    /// result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned,
761    /// indicating whether the rounded inverse hyperbolic secant is less than, equal to, or greater
762    /// than the exact inverse hyperbolic secant. Although `NaN`s are not comparable to any
763    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
764    ///
765    /// See [`RoundingMode`] for a description of the possible rounding modes.
766    ///
767    /// $$
768    /// f(x,p,m) = \operatorname{asech} x+\varepsilon.
769    /// $$
770    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
771    ///   assumed to be 0.
772    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
773    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$.
774    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
775    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$.
776    ///
777    /// These bounds do not apply when the result underflows; see below.
778    ///
779    /// If the output has a precision, it is `prec`.
780    ///
781    /// Special cases:
782    /// - $f(0,p,m)=\infty$
783    /// - $f(1,p,m)=0.0$
784    /// - $f(x,p,m)=\text{NaN}$ if $x<0$ or $x>1$
785    ///
786    /// Overflow and underflow:
787    /// - The result never overflows: for $0<x<1$ with denominator $d$, $\operatorname{asech} x <
788    ///   \ln(2/x) \leq \ln 2d$.
789    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
790    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
791    ///   instead.
792    /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
793    /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
794    ///   instead.
795    ///
796    /// Underflow requires an $x$ within $2^{-2^{31}}$ of 1, since $\operatorname{asech}(1-t) >
797    /// \sqrt t$, and so a denominator of more than $2^{31}$ bits.
798    ///
799    /// If you know you'll be using `Nearest`, consider using [`Float::asech_rational_prec`]
800    /// instead.
801    ///
802    /// # Worst-case complexity
803    /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
804    ///
805    /// $M(n, m) = O(n \log n + m \log m)$
806    ///
807    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
808    /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
809    /// the input is handled with `Rational` arithmetic.
810    ///
811    /// # Panics
812    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
813    /// with the given precision (which is the case for every $x$ with $0<x<1$).
814    ///
815    /// # Examples
816    /// ```
817    /// use malachite_base::rounding_modes::RoundingMode::*;
818    /// use malachite_float::Float;
819    /// use malachite_q::Rational;
820    /// use std::cmp::Ordering::*;
821    ///
822    /// let (c, o) = Float::asech_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Floor);
823    /// assert_eq!(c.to_string(), "1.75");
824    /// assert_eq!(o, Less);
825    ///
826    /// let (c, o) = Float::asech_rational_prec_round(Rational::from_unsigneds(1u8, 3), 5, Ceiling);
827    /// assert_eq!(c.to_string(), "1.81");
828    /// assert_eq!(o, Greater);
829    ///
830    /// let (c, o) = Float::asech_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Floor);
831    /// assert_eq!(c.to_string(), "1.7627468");
832    /// assert_eq!(o, Less);
833    ///
834    /// let (c, o) =
835    ///     Float::asech_rational_prec_round(Rational::from_unsigneds(1u8, 3), 20, Ceiling);
836    /// assert_eq!(c.to_string(), "1.7627487");
837    /// assert_eq!(o, Greater);
838    /// ```
839    #[inline]
840    #[allow(clippy::needless_pass_by_value)]
841    pub fn asech_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
842        Self::asech_rational_prec_round_ref(&x, prec, rm)
843    }
844
845    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Rational`], rounding
846    /// the result to the specified precision and with the specified rounding mode and returning the
847    /// result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also
848    /// returned, indicating whether the rounded inverse hyperbolic secant is less than, equal to,
849    /// or greater than the exact inverse hyperbolic secant. Although `NaN`s are not comparable to
850    /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
851    ///
852    /// See [`RoundingMode`] for a description of the possible rounding modes.
853    ///
854    /// $$
855    /// f(x,p,m) = \operatorname{asech} x+\varepsilon.
856    /// $$
857    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
858    ///   assumed to be 0.
859    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is not `Nearest`, then
860    ///   $|\varepsilon| < 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p+1}$.
861    /// - If $\operatorname{asech} x$ is finite and nonzero, and $m$ is `Nearest`, then
862    ///   $|\varepsilon| \leq 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$.
863    ///
864    /// These bounds do not apply when the result underflows; see below.
865    ///
866    /// If the output has a precision, it is `prec`.
867    ///
868    /// Special cases:
869    /// - $f(0,p,m)=\infty$
870    /// - $f(1,p,m)=0.0$
871    /// - $f(x,p,m)=\text{NaN}$ if $x<0$ or $x>1$
872    ///
873    /// Overflow and underflow:
874    /// - The result never overflows: for $0<x<1$ with denominator $d$, $\operatorname{asech} x <
875    ///   \ln(2/x) \leq \ln 2d$.
876    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
877    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
878    ///   instead.
879    /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
880    /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
881    ///   instead.
882    ///
883    /// Underflow requires an $x$ within $2^{-2^{31}}$ of 1, since $\operatorname{asech}(1-t) >
884    /// \sqrt t$, and so a denominator of more than $2^{31}$ bits.
885    ///
886    /// If you know you'll be using `Nearest`, consider using [`Float::asech_rational_prec_ref`]
887    /// instead.
888    ///
889    /// # Worst-case complexity
890    /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
891    ///
892    /// $M(n, m) = O(n \log n + m \log m)$
893    ///
894    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
895    /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
896    /// the input is handled with `Rational` arithmetic.
897    ///
898    /// # Panics
899    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
900    /// with the given precision (which is the case for every $x$ with $0<x<1$).
901    ///
902    /// # Examples
903    /// ```
904    /// use malachite_base::rounding_modes::RoundingMode::*;
905    /// use malachite_float::Float;
906    /// use malachite_q::Rational;
907    /// use std::cmp::Ordering::*;
908    ///
909    /// let (c, o) =
910    ///     Float::asech_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 3), 5, Floor);
911    /// assert_eq!(c.to_string(), "1.75");
912    /// assert_eq!(o, Less);
913    ///
914    /// let (c, o) =
915    ///     Float::asech_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 3), 5, Ceiling);
916    /// assert_eq!(c.to_string(), "1.81");
917    /// assert_eq!(o, Greater);
918    ///
919    /// let (c, o) =
920    ///     Float::asech_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 3), 20, Floor);
921    /// assert_eq!(c.to_string(), "1.7627468");
922    /// assert_eq!(o, Less);
923    ///
924    /// let (c, o) =
925    ///     Float::asech_rational_prec_round_ref(&Rational::from_unsigneds(1u8, 3), 20, Ceiling);
926    /// assert_eq!(c.to_string(), "1.7627487");
927    /// assert_eq!(o, Greater);
928    /// ```
929    pub fn asech_rational_prec_round_ref(
930        x: &Rational,
931        prec: u64,
932        rm: RoundingMode,
933    ) -> (Self, Ordering) {
934        assert_ne!(prec, 0);
935        match x.sign() {
936            // asech is NaN below 0
937            Less => (Self::NAN, Equal),
938            // asech(0) = +Inf
939            Equal => (Self::INFINITY, Equal),
940            // asech(x) = acosh(1/x), and the reciprocal of a `Rational` is exact
941            Greater => Self::acosh_rational_prec_round(x.reciprocal(), prec, rm),
942        }
943    }
944
945    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Rational`], rounding
946    /// the result to the nearest value of the specified precision and returning the result as a
947    /// [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating
948    /// whether the rounded inverse hyperbolic secant is less than, equal to, or greater than the
949    /// exact inverse hyperbolic secant. Although `NaN`s are not comparable to any [`Float`],
950    /// whenever this function returns a `NaN` it also returns `Equal`.
951    ///
952    /// If the inverse hyperbolic secant is equidistant from two [`Float`]s with the specified
953    /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
954    /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
955    ///
956    /// $$
957    /// f(x,p) = \operatorname{asech} x+\varepsilon,
958    /// $$
959    /// where, if $\operatorname{asech} x$ is finite and nonzero, $|\varepsilon| \leq
960    /// 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$ (unless the result underflows; see
961    /// below).
962    ///
963    /// If the output has a precision, it is `prec`.
964    ///
965    /// Special cases:
966    /// - $f(0,p)=\infty$
967    /// - $f(1,p)=0.0$
968    /// - $f(x,p)=\text{NaN}$ if $x<0$ or $x>1$
969    ///
970    /// Overflow and underflow:
971    /// - The result never overflows: for $0<x<1$ with denominator $d$, $\operatorname{asech} x <
972    ///   \ln(2/x) \leq \ln 2d$.
973    /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
974    /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
975    ///
976    /// Underflow requires an $x$ within $2^{-2^{31}}$ of 1, since $\operatorname{asech}(1-t) >
977    /// \sqrt t$, and so a denominator of more than $2^{31}$ bits.
978    ///
979    /// If you want to use a rounding mode other than `Nearest`, consider using
980    /// [`Float::asech_rational_prec_round`] instead.
981    ///
982    /// # Worst-case complexity
983    /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
984    ///
985    /// $M(n, m) = O(n \log n + m \log m)$
986    ///
987    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
988    /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
989    /// the input is handled with `Rational` arithmetic.
990    ///
991    /// # Panics
992    /// Panics if `prec` is zero.
993    ///
994    /// # Examples
995    /// ```
996    /// use malachite_base::num::basic::traits::{One, Two, Zero};
997    /// use malachite_float::Float;
998    /// use malachite_q::Rational;
999    /// use std::cmp::Ordering::*;
1000    ///
1001    /// let (c, o) = Float::asech_rational_prec(Rational::from_unsigneds(1u8, 3), 5);
1002    /// assert_eq!(c.to_string(), "1.75");
1003    /// assert_eq!(o, Less);
1004    ///
1005    /// let (c, o) = Float::asech_rational_prec(Rational::from_unsigneds(1u8, 3), 20);
1006    /// assert_eq!(c.to_string(), "1.7627468");
1007    /// assert_eq!(o, Less);
1008    ///
1009    /// let (c, o) = Float::asech_rational_prec(Rational::ONE, 10);
1010    /// assert_eq!(c.to_string(), "0.0");
1011    /// assert_eq!(o, Equal);
1012    ///
1013    /// let (c, o) = Float::asech_rational_prec(Rational::ZERO, 10);
1014    /// assert_eq!(c.to_string(), "Infinity");
1015    /// assert_eq!(o, Equal);
1016    ///
1017    /// let (c, o) = Float::asech_rational_prec(Rational::TWO, 10);
1018    /// assert!(c.is_nan());
1019    /// assert_eq!(o, Equal);
1020    /// ```
1021    #[inline]
1022    #[allow(clippy::needless_pass_by_value)]
1023    pub fn asech_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
1024        Self::asech_rational_prec_round_ref(&x, prec, Nearest)
1025    }
1026
1027    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Rational`], rounding
1028    /// the result to the nearest value of the specified precision and returning the result as a
1029    /// [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also returned,
1030    /// indicating whether the rounded inverse hyperbolic secant is less than, equal to, or greater
1031    /// than the exact inverse hyperbolic secant. Although `NaN`s are not comparable to any
1032    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1033    ///
1034    /// If the inverse hyperbolic secant is equidistant from two [`Float`]s with the specified
1035    /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
1036    /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
1037    ///
1038    /// $$
1039    /// f(x,p) = \operatorname{asech} x+\varepsilon,
1040    /// $$
1041    /// where, if $\operatorname{asech} x$ is finite and nonzero, $|\varepsilon| \leq
1042    /// 2^{\lfloor\log_2 \operatorname{asech} x\rfloor-p}$ (unless the result underflows; see
1043    /// below).
1044    ///
1045    /// If the output has a precision, it is `prec`.
1046    ///
1047    /// Special cases:
1048    /// - $f(0,p)=\infty$
1049    /// - $f(1,p)=0.0$
1050    /// - $f(x,p)=\text{NaN}$ if $x<0$ or $x>1$
1051    ///
1052    /// Overflow and underflow:
1053    /// - The result never overflows: for $0<x<1$ with denominator $d$, $\operatorname{asech} x <
1054    ///   \ln(2/x) \leq \ln 2d$.
1055    /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1056    /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1057    ///
1058    /// Underflow requires an $x$ within $2^{-2^{31}}$ of 1, since $\operatorname{asech}(1-t) >
1059    /// \sqrt t$, and so a denominator of more than $2^{31}$ bits.
1060    ///
1061    /// If you want to use a rounding mode other than `Nearest`, consider using
1062    /// [`Float::asech_rational_prec_round_ref`] instead.
1063    ///
1064    /// # Worst-case complexity
1065    /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
1066    ///
1067    /// $M(n, m) = O(n \log n + m \log m)$
1068    ///
1069    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1070    /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
1071    /// the input is handled with `Rational` arithmetic.
1072    ///
1073    /// # Panics
1074    /// Panics if `prec` is zero.
1075    ///
1076    /// # Examples
1077    /// ```
1078    /// use malachite_base::num::basic::traits::{One, Two, Zero};
1079    /// use malachite_float::Float;
1080    /// use malachite_q::Rational;
1081    /// use std::cmp::Ordering::*;
1082    ///
1083    /// let (c, o) = Float::asech_rational_prec_ref(&Rational::from_unsigneds(1u8, 3), 5);
1084    /// assert_eq!(c.to_string(), "1.75");
1085    /// assert_eq!(o, Less);
1086    ///
1087    /// let (c, o) = Float::asech_rational_prec_ref(&Rational::from_unsigneds(1u8, 3), 20);
1088    /// assert_eq!(c.to_string(), "1.7627468");
1089    /// assert_eq!(o, Less);
1090    ///
1091    /// let (c, o) = Float::asech_rational_prec_ref(&Rational::ONE, 10);
1092    /// assert_eq!(c.to_string(), "0.0");
1093    /// assert_eq!(o, Equal);
1094    ///
1095    /// let (c, o) = Float::asech_rational_prec_ref(&Rational::ZERO, 10);
1096    /// assert_eq!(c.to_string(), "Infinity");
1097    /// assert_eq!(o, Equal);
1098    ///
1099    /// let (c, o) = Float::asech_rational_prec_ref(&Rational::TWO, 10);
1100    /// assert!(c.is_nan());
1101    /// assert_eq!(o, Equal);
1102    /// ```
1103    #[inline]
1104    pub fn asech_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
1105        Self::asech_rational_prec_round_ref(x, prec, Nearest)
1106    }
1107}
1108
1109impl Asech for Float {
1110    type Output = Self;
1111
1112    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], taking it
1113    /// by value.
1114    ///
1115    /// If the output has a precision, it is the precision of the input. If the inverse hyperbolic
1116    /// secant is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
1117    /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
1118    /// `Nearest` rounding mode.
1119    ///
1120    /// $$
1121    /// f(x) = \operatorname{asech} x+\varepsilon.
1122    /// $$
1123    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
1124    ///   assumed to be 0.
1125    /// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1126    ///   \operatorname{asech} x\rfloor-p}$, where $p$ is the precision of the input.
1127    ///
1128    /// Special cases:
1129    /// - $f(\text{NaN})=\text{NaN}$
1130    /// - $f(\pm\infty)=\text{NaN}$
1131    /// - $f(\pm0.0)=\infty$
1132    /// - $f(1)=0.0$
1133    /// - $f(x)=\text{NaN}$ if $x<0$ or $x>1$
1134    ///
1135    /// See the [`Float::asech_round`] documentation for information on overflow and underflow.
1136    ///
1137    /// If you want to use a rounding mode other than `Nearest`, consider using
1138    /// [`Float::asech_round`] instead. If you want to specify the output precision, consider using
1139    /// [`Float::asech_prec`]. If you want both of these things, consider using
1140    /// [`Float::asech_prec_round`].
1141    ///
1142    /// # Worst-case complexity
1143    /// $T(n) = O(n (\log n)^2 \log\log n)$
1144    ///
1145    /// $M(n) = O(n \log n)$
1146    ///
1147    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1148    ///
1149    /// # Examples
1150    /// ```
1151    /// use malachite_base::num::arithmetic::traits::Asech;
1152    /// use malachite_base::num::basic::traits::*;
1153    /// use malachite_float::Float;
1154    ///
1155    /// assert!(Float::NAN.asech().is_nan());
1156    /// assert!(Float::INFINITY.asech().is_nan());
1157    /// assert!(Float::NEGATIVE_INFINITY.asech().is_nan());
1158    /// assert_eq!(Float::ZERO.asech().to_string(), "Infinity");
1159    /// assert_eq!(Float::NEGATIVE_ZERO.asech().to_string(), "Infinity");
1160    /// assert_eq!(Float::ONE.asech().to_string(), "0.0");
1161    /// assert!(Float::TWO.asech().is_nan());
1162    /// assert!(Float::NEGATIVE_ONE.asech().is_nan());
1163    /// assert_eq!(
1164    ///     (Float::one_prec(100) >> 1u32).asech().to_string(),
1165    ///     "1.3169578969248167086250463473073"
1166    /// );
1167    /// assert_eq!(
1168    ///     (Float::one_prec(100) >> 2u32).asech().to_string(),
1169    ///     "2.0634370688955605467272811726205"
1170    /// );
1171    /// ```
1172    #[inline]
1173    fn asech(self) -> Self {
1174        let prec = self.significant_bits();
1175        self.asech_prec_round(prec, Nearest).0
1176    }
1177}
1178
1179impl Asech for &Float {
1180    type Output = Float;
1181
1182    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], taking it
1183    /// by reference.
1184    ///
1185    /// If the output has a precision, it is the precision of the input. If the inverse hyperbolic
1186    /// secant is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
1187    /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
1188    /// `Nearest` rounding mode.
1189    ///
1190    /// $$
1191    /// f(x) = \operatorname{asech} x+\varepsilon.
1192    /// $$
1193    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
1194    ///   assumed to be 0.
1195    /// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1196    ///   \operatorname{asech} x\rfloor-p}$, where $p$ is the precision of the input.
1197    ///
1198    /// Special cases:
1199    /// - $f(\text{NaN})=\text{NaN}$
1200    /// - $f(\pm\infty)=\text{NaN}$
1201    /// - $f(\pm0.0)=\infty$
1202    /// - $f(1)=0.0$
1203    /// - $f(x)=\text{NaN}$ if $x<0$ or $x>1$
1204    ///
1205    /// See the [`Float::asech_round`] documentation for information on overflow and underflow.
1206    ///
1207    /// If you want to use a rounding mode other than `Nearest`, consider using
1208    /// [`Float::asech_round_ref`] instead. If you want to specify the output precision, consider
1209    /// using [`Float::asech_prec_ref`]. If you want both of these things, consider using
1210    /// [`Float::asech_prec_round_ref`].
1211    ///
1212    /// # Worst-case complexity
1213    /// $T(n) = O(n (\log n)^2 \log\log n)$
1214    ///
1215    /// $M(n) = O(n \log n)$
1216    ///
1217    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1218    ///
1219    /// # Examples
1220    /// ```
1221    /// use malachite_base::num::arithmetic::traits::Asech;
1222    /// use malachite_base::num::basic::traits::*;
1223    /// use malachite_float::Float;
1224    ///
1225    /// assert!((&Float::NAN).asech().is_nan());
1226    /// assert!((&Float::INFINITY).asech().is_nan());
1227    /// assert!((&Float::NEGATIVE_INFINITY).asech().is_nan());
1228    /// assert_eq!((&Float::ZERO).asech().to_string(), "Infinity");
1229    /// assert_eq!((&Float::NEGATIVE_ZERO).asech().to_string(), "Infinity");
1230    /// assert_eq!((&Float::ONE).asech().to_string(), "0.0");
1231    /// assert!((&Float::TWO).asech().is_nan());
1232    /// assert!((&Float::NEGATIVE_ONE).asech().is_nan());
1233    /// assert_eq!(
1234    ///     (&(Float::one_prec(100) >> 1u32)).asech().to_string(),
1235    ///     "1.3169578969248167086250463473073"
1236    /// );
1237    /// assert_eq!(
1238    ///     (&(Float::one_prec(100) >> 2u32)).asech().to_string(),
1239    ///     "2.0634370688955605467272811726205"
1240    /// );
1241    /// ```
1242    #[inline]
1243    fn asech(self) -> Float {
1244        self.asech_prec_round_ref(self.significant_bits(), Nearest)
1245            .0
1246    }
1247}
1248
1249impl AsechAssign for Float {
1250    /// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Float`], in place.
1251    ///
1252    /// If the output has a precision, it is the precision of the input. If the inverse hyperbolic
1253    /// secant is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
1254    /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
1255    /// `Nearest` rounding mode.
1256    ///
1257    /// $$
1258    /// x \gets \operatorname{asech} x+\varepsilon.
1259    /// $$
1260    /// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or
1261    ///   assumed to be 0.
1262    /// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1263    ///   \operatorname{asech} x\rfloor-p}$, where $p$ is the precision of the input.
1264    ///
1265    /// See the [`Float::asech`] documentation for information on special cases, overflow, and
1266    /// underflow.
1267    ///
1268    /// If you want to use a rounding mode other than `Nearest`, consider using
1269    /// [`Float::asech_round_assign`] instead. If you want to specify the output precision, consider
1270    /// using [`Float::asech_prec_assign`]. If you want both of these things, consider using
1271    /// [`Float::asech_prec_round_assign`].
1272    ///
1273    /// # Worst-case complexity
1274    /// $T(n) = O(n (\log n)^2 \log\log n)$
1275    ///
1276    /// $M(n) = O(n \log n)$
1277    ///
1278    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1279    ///
1280    /// # Examples
1281    /// ```
1282    /// use malachite_base::num::arithmetic::traits::AsechAssign;
1283    /// use malachite_base::num::basic::traits::*;
1284    /// use malachite_float::Float;
1285    ///
1286    /// let mut x = Float::NAN;
1287    /// x.asech_assign();
1288    /// assert!(x.is_nan());
1289    ///
1290    /// let mut x = Float::INFINITY;
1291    /// x.asech_assign();
1292    /// assert!(x.is_nan());
1293    ///
1294    /// let mut x = Float::ZERO;
1295    /// x.asech_assign();
1296    /// assert_eq!(x.to_string(), "Infinity");
1297    ///
1298    /// let mut x = Float::NEGATIVE_ZERO;
1299    /// x.asech_assign();
1300    /// assert_eq!(x.to_string(), "Infinity");
1301    ///
1302    /// let mut x = Float::ONE;
1303    /// x.asech_assign();
1304    /// assert_eq!(x.to_string(), "0.0");
1305    ///
1306    /// let mut x = Float::TWO;
1307    /// x.asech_assign();
1308    /// assert!(x.is_nan());
1309    ///
1310    /// let mut x = Float::one_prec(100) >> 1u32;
1311    /// x.asech_assign();
1312    /// assert_eq!(x.to_string(), "1.3169578969248167086250463473073");
1313    ///
1314    /// let mut x = Float::one_prec(100) >> 2u32;
1315    /// x.asech_assign();
1316    /// assert_eq!(x.to_string(), "2.0634370688955605467272811726205");
1317    /// ```
1318    #[inline]
1319    fn asech_assign(&mut self) {
1320        let prec = self.significant_bits();
1321        self.asech_prec_round_assign(prec, Nearest);
1322    }
1323}
1324
1325/// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a primitive float. Using
1326/// this function is more accurate than using the default `asech` function or the one provided by
1327/// `libm`.
1328///
1329/// $$
1330/// f(x) = \operatorname{asech} x+\varepsilon.
1331/// $$
1332/// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed
1333///   to be 0.
1334/// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1335///   \operatorname{asech} x\rfloor-p}$, where $p$ is the precision of the output (24 if `T` is a
1336///   [`f32`] and 53 if `T` is a [`f64`]).
1337///
1338/// Special cases:
1339/// - $f(\text{NaN})=\text{NaN}$
1340/// - $f(\pm\infty)=\text{NaN}$
1341/// - $f(\pm0.0)=\infty$
1342/// - $f(1)=0.0$
1343/// - $f(x)=\text{NaN}$ if $x<0$ or $x>1$
1344///
1345/// Overflow is not possible. The result is subnormal only when $x$ is, and then it is $x$ itself,
1346/// since $|\operatorname{asech} x - x| < |x|^3/2$.
1347///
1348/// # Worst-case complexity
1349/// Constant time and additional memory.
1350///
1351/// # Examples
1352/// ```
1353/// use malachite_base::num::basic::traits::NegativeInfinity;
1354/// use malachite_base::num::float::NiceFloat;
1355/// use malachite_float::float::arithmetic::asech::primitive_float_asech;
1356///
1357/// assert!(primitive_float_asech(f32::NAN).is_nan());
1358/// assert!(primitive_float_asech(f32::INFINITY).is_nan());
1359/// assert!(primitive_float_asech(f32::NEGATIVE_INFINITY).is_nan());
1360/// assert_eq!(
1361///     NiceFloat(primitive_float_asech(0.0f32)),
1362///     NiceFloat(f32::INFINITY)
1363/// );
1364/// assert_eq!(NiceFloat(primitive_float_asech(1.0f32)), NiceFloat(0.0));
1365/// assert!(primitive_float_asech(2.0f32).is_nan());
1366/// assert_eq!(
1367///     NiceFloat(primitive_float_asech(0.5f32)),
1368///     NiceFloat(1.316958)
1369/// );
1370/// assert_eq!(
1371///     NiceFloat(primitive_float_asech(0.5f64)),
1372///     NiceFloat(1.3169578969248168)
1373/// );
1374/// assert_eq!(
1375///     NiceFloat(primitive_float_asech(0.1f64)),
1376///     NiceFloat(2.993222846126381)
1377/// );
1378/// ```
1379#[inline]
1380#[allow(clippy::type_repetition_in_bounds)]
1381pub fn primitive_float_asech<T: PrimitiveFloat>(x: T) -> T
1382where
1383    Float: From<T> + PartialOrd<T>,
1384    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1385{
1386    emulate_float_to_float_fn(Float::asech_prec, x)
1387}
1388
1389/// Computes $\operatorname{asech} x$, the inverse hyperbolic secant of a [`Rational`], returning
1390/// the result as a primitive float. The result is correctly rounded.
1391///
1392/// $$
1393/// f(x) = \operatorname{asech} x+\varepsilon.
1394/// $$
1395/// - If $\operatorname{asech} x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed
1396///   to be 0.
1397/// - If $\operatorname{asech} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1398///   \operatorname{asech} x\rfloor-p}$, where $p$ is the precision of the output (typically 24 if
1399///   `T` is a [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
1400///
1401/// Special cases:
1402/// - $f(0)=\infty$
1403/// - $f(1)=0.0$
1404/// - $f(x)=\text{NaN}$ if $x<0$ or $x>1$
1405///
1406/// Overflow is not possible. Underflow is: an `x` close enough to 1 gives `0.0`.
1407///
1408/// # Worst-case complexity
1409/// $T(m) = O(m (\log m)^2 \log\log m)$
1410///
1411/// $M(m) = O(m \log m)$
1412///
1413/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`.
1414///
1415/// # Examples
1416/// ```
1417/// use malachite_base::num::basic::traits::{One, Two, Zero};
1418/// use malachite_base::num::float::NiceFloat;
1419/// use malachite_float::float::arithmetic::asech::primitive_float_asech_rational;
1420/// use malachite_q::Rational;
1421///
1422/// assert_eq!(
1423///     NiceFloat(primitive_float_asech_rational::<f64>(&Rational::ZERO)),
1424///     NiceFloat(f64::INFINITY)
1425/// );
1426/// assert_eq!(
1427///     NiceFloat(primitive_float_asech_rational::<f64>(&Rational::ONE)),
1428///     NiceFloat(0.0)
1429/// );
1430/// assert!(primitive_float_asech_rational::<f64>(&Rational::TWO).is_nan());
1431/// assert_eq!(
1432///     NiceFloat(primitive_float_asech_rational::<f64>(
1433///         &Rational::from_unsigneds(1u8, 3)
1434///     )),
1435///     NiceFloat(1.762747174039086)
1436/// );
1437/// ```
1438#[inline]
1439#[allow(clippy::type_repetition_in_bounds)]
1440pub fn primitive_float_asech_rational<T: PrimitiveFloat>(x: &Rational) -> T
1441where
1442    Float: PartialOrd<T>,
1443    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1444{
1445    emulate_rational_to_float_fn(Float::asech_rational_prec_ref, x)
1446}