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