Skip to main content

malachite_float/float/arithmetic/
csch.rs

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