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}