malachite_float/float/arithmetic/asinh.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5// Copyright 2001-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::atan::alternating_odd_series;
17use crate::float::arithmetic::cosh::{monotone_rational_via_floats, same_rounding};
18use crate::float::arithmetic::round_near_x::{
19 LEADING_TERM_MIN_EXPONENT, round_rational_leading_term, small_input_shortcut,
20};
21use crate::float::arithmetic::sin::{UNDERFLOW_EXPONENT, underflowed};
22use crate::{Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
23use core::cmp::Ordering::{self, Equal};
24use core::cmp::max;
25use malachite_base::fail_on_untested_path;
26use malachite_base::num::arithmetic::traits::{Abs, Asinh, AsinhAssign, CeilingLogBase2, Ln, Sqrt};
27use malachite_base::num::basic::floats::PrimitiveFloat;
28use malachite_base::num::basic::integers::PrimitiveInt;
29use malachite_base::num::basic::traits::{NaN as NaNTrait, One, Zero as ZeroTrait};
30use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
31use malachite_base::num::logic::traits::SignificantBits;
32use malachite_base::rounding_modes::RoundingMode::{self, *};
33use malachite_nz::natural::arithmetic::float::round::float_can_round;
34use malachite_nz::platform::Limb;
35use malachite_q::Rational;
36
37// The largest working precision at which `ln_of_large_sum` may use ln 2 in place of ln(1 + sqrt(1
38// ± (1/x)^2)). The two differ by less than (1/x)^2 / 2 < 2^(-2^30), and the result's exponent is
39// at least 29, so the difference stays below half an ulp of the result as long as the working
40// precision is at most 2^30 + 28.
41const LN_2_SHORTCUT_MAX_PREC: u64 = (1 << 30) + 28;
42
43// asinh(|x|) = ln(sqrt(x^2 + 1) + |x|), evaluated at a working precision of `wp`. x^2 must not
44// overflow.
45pub(crate) fn asinh_abs_general(x_abs: &Float, wp: u64) -> Float {
46 x_abs
47 .square_prec_round_ref(wp, Floor)
48 .0
49 .add_round(Float::ONE, Floor)
50 .0
51 .sqrt()
52 .add_prec_val_ref(x_abs, wp)
53 .0
54 .ln()
55}
56
57// ln(x) + ln(1 + sqrt(1 + (1/x)^2)) if `plus`, which is asinh(x), or ln(x) + ln(1 + sqrt(1 -
58// (1/x)^2)) otherwise, which is acosh(x), evaluated at a working precision of `wp` for a positive x
59// whose square would overflow. Both identities are exact and cannot overflow, and at any practical
60// precision the second logarithm is ln 2 to within half an ulp of the result. The error is at most
61// half an ulp each from ln(x), ln 2, the addition, and the replacement of the second logarithm by
62// ln 2, so below 2 ulps of the result.
63pub(crate) fn ln_of_large_sum(x: &Float, wp: u64, plus: bool) -> Float {
64 let ln_x = x.ln_prec_ref(wp).0;
65 let correction = if wp <= LN_2_SHORTCUT_MAX_PREC {
66 // ln 2 is needed only to the result's ulp, and the result has the exponent of ln(x) or one
67 // more, so wp - EXP(ln(x)) bits suffice, as in MPFR's overflow branch
68 let exp_ln_x = u64::from(ln_x.get_exponent().unwrap().unsigned_abs());
69 Float::ln_2_prec(wp.saturating_sub(exp_ln_x).max(1)).0
70 } else {
71 fail_on_untested_path("ln_of_large_sum, full correction");
72 let reciprocal_squared = x
73 .reciprocal_prec_round_ref(wp, Floor)
74 .0
75 .square_round(Floor)
76 .0;
77 let inner = if plus {
78 Float::ONE.add_round(reciprocal_squared, Floor).0
79 } else {
80 Float::ONE.sub_round(reciprocal_squared, Floor).0
81 };
82 (inner.sqrt() + Float::ONE).ln()
83 };
84 ln_x + correction
85}
86
87// Whether x^2 can overflow: x < 2^EXP(x), so x^2 < 2^(2 EXP(x)), which is in range as long as
88// EXP(x) is at most MAX_EXPONENT / 2.
89pub(crate) const fn square_may_overflow(x: &Float) -> bool {
90 x.get_exponent().unwrap() > Float::MAX_EXPONENT >> 1
91}
92
93// The end of a Ziv loop iteration: rounds an approximation t, whose error is below 2^(EXP(t) - wp +
94// err), to precision `prec` with rounding mode `rm`, if that error allows it. Like MPFR's, `err` is
95// signed, and a nonpositive wp - err means that t cannot be rounded yet. The test does not depend
96// on the sign of t, so a caller may negate t first.
97pub(crate) fn round_with_error(
98 t: Float,
99 wp: u64,
100 err: i64,
101 prec: u64,
102 rm: RoundingMode,
103) -> Option<(Float, Ordering)> {
104 let bits = i64::exact_from(wp) - err;
105 (bits > 0
106 && float_can_round(
107 t.significand_ref().unwrap(),
108 u64::exact_from(bits),
109 prec,
110 rm,
111 ))
112 .then(|| Float::from_float_prec_round(t, prec, rm))
113}
114
115// This is mpfr_asinh from asinh.c, MPFR 4.2.2, where the input is finite and nonzero.
116//
117// MPFR computes x^2 in an extended exponent range, so it never overflows. Here it overflows once
118// EXP(x) exceeds MAX_EXPONENT / 2, and with `Floor` it would saturate to the largest finite `Float`
119// and silently give a wrong result, so those inputs go through `ln_of_large_sum`.
120fn asinh_prec_round_normal_ref(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
121 assert_ne!(rm, Exact, "Inexact asinh");
122 let exp_x = i64::from(x.get_exponent().unwrap());
123 // asinh(x) = x - x^3/6 + ... so the error is < 2^(3*EXP(x)-2)
124 if let Some(result) = small_input_shortcut(x, -(exp_x << 1), 2, false, prec, rm) {
125 return result;
126 }
127 let negative = *x < 0u32;
128 let x_abs = x.abs();
129 let large = square_may_overflow(x);
130 // the optimal number of bits: see algorithms.tex
131 let mut working_prec = prec + 4 + prec.ceiling_log_base_2();
132 let mut increment = Limb::WIDTH;
133 loop {
134 let t = if large {
135 ln_of_large_sum(&x_abs, working_prec, true)
136 } else {
137 asinh_abs_general(&x_abs, working_prec)
138 };
139 if t.is_normal() {
140 // error estimate: see algorithms.tex. In the large case the error is below 2 ulps of t,
141 // as `ln_of_large_sum` explains, which an err of 2 covers with room to spare.
142 let err = if large {
143 2
144 } else {
145 max(4 - i64::from(t.get_exponent().unwrap()), 0) + 1
146 };
147 if let Some(result) =
148 round_with_error(if negative { -t } else { t }, working_prec, err, prec, rm)
149 {
150 return result;
151 }
152 }
153 working_prec += increment;
154 increment = working_prec >> 1;
155 }
156}
157
158// Computes asinh(x) for a nonzero `Rational` x with |x| < 1/2 from the series x - x^3/6 + 3 x^5/40
159// - ..., whose kth term is c_k x^(2k+1) / (2k+1) with c_k = (2k)! / (4^k (k!)^2) = c_(k-1) (2k - 1)
160// / (2k). The terms alternate in sign and decrease in magnitude.
161fn asinh_series(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
162 alternating_odd_series(x, prec, rm, |k| {
163 Some(Rational::from_unsigneds((k << 1) - 1, k << 1))
164 })
165}
166
167// Computes ln(2x) + c for a positive `Rational` x too large to be a `Float`, where c is unknown but
168// positive if `plus` is true and negative otherwise, and |c| < 2^(2 - 2 EXP(x)). The result exceeds
169// 2^29, so |c| is below an ulp of the result at any working precision below 2 EXP(x), more than
170// 2^31 bits. ln(2x) rounded down and rounded up, with the bound on c's side moved one more ulp,
171// therefore bracket ln(2x) + c.
172pub(crate) fn ln_of_large_rational_sum(
173 x: &Rational,
174 exp_x: i64,
175 prec: u64,
176 rm: RoundingMode,
177 plus: bool,
178) -> (Float, Ordering) {
179 let two_x = x << 1u32;
180 let mut working_prec = prec + 10;
181 let mut increment = Limb::WIDTH;
182 loop {
183 assert!(
184 working_prec < u64::exact_from(exp_x) << 1,
185 "ln_of_large_rational_sum needs a working precision below 2 EXP(x)"
186 );
187 let mut lo = Float::ln_rational_prec_round_ref(&two_x, working_prec, Floor).0;
188 let mut hi = Float::ln_rational_prec_round_ref(&two_x, working_prec, Ceiling).0;
189 if plus {
190 hi.increment();
191 } else {
192 lo.decrement();
193 }
194 if let Some(result) = same_rounding(
195 Float::from_float_prec_round(lo, prec, rm),
196 Float::from_float_prec_round(hi, prec, rm),
197 ) {
198 return result;
199 }
200 fail_on_untested_path("ln_of_large_rational_sum, retry");
201 working_prec += increment;
202 increment = working_prec >> 1;
203 }
204}
205
206// Computes asinh(x) for a `Rational` x too large to be a `Float`. asinh(|x|) = ln(2|x|) + c with 0
207// < c < 1/(4x^2) < 2^(-2 EXP(x)).
208fn asinh_rational_huge(x: &Rational, exp_x: i64, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
209 if *x > 0u32 {
210 ln_of_large_rational_sum(x, exp_x, prec, rm, true)
211 } else {
212 let (y, o) = ln_of_large_rational_sum(&-x, exp_x, prec, -rm, true);
213 (-y, o.reverse())
214 }
215}
216
217// Computes asinh(x) for a nonzero `Rational` x, rounded to precision `prec` with rounding mode
218// `rm`. (x = 0 is handled by the caller.) The result is never exactly representable, so `rm` must
219// not be `Exact`.
220fn asinh_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
221 assert_ne!(rm, Exact, "Inexact asinh");
222 let exp_x = x.floor_log_base_2_abs() + 1; // the MPFR-style exponent of x
223 if exp_x < UNDERFLOW_EXPONENT {
224 // |asinh x| < |x| < 2^(MIN_EXPONENT - 2), below half the smallest positive `Float`, so the
225 // result is zero or that `Float` by the rounding mode alone
226 return underflowed(*x > 0u32, prec, rm);
227 }
228 // asinh(x) = x(1 - x^2/6 + ...), so |x| exceeds |asinh x| by less than 2^(3 EXP(x) - 2), and
229 // once that is below the distance from x to the nearest (prec + 1)-bit dyadic other than x
230 // itself, x's own rounding, nudged toward zero, is the answer; as for `atan_rational`.
231 if exp_x > LEADING_TERM_MIN_EXPONENT
232 && -(exp_x << 1) > i64::exact_from(prec + x.denominator_ref().significant_bits()) + 4
233 {
234 return round_rational_leading_term(x.abs(), *x > 0u32, false, prec, rm);
235 }
236 // For |x| <= 1/2 the partial sums of the series bracket asinh x within a relative width below
237 // x^4, which decides the rounding once x^4 is below 2^-(prec + 3); a handful of terms is
238 // cheaper than a `Float` inverse hyperbolic sine at the working precision.
239 if exp_x < 0 && -(exp_x << 2) > i64::exact_from(prec) + 3 {
240 return asinh_series(x, prec, rm);
241 }
242 if exp_x > Float::MAX_EXPONENT_I64 {
243 return asinh_rational_huge(x, exp_x, prec, rm);
244 }
245 // asinh is increasing, so bracket x between the Floats x_lo <= x <= x_hi, take the inverse
246 // hyperbolic sine of both, and increase the working precision until the two round to the same
247 // result, which the exact asinh(x), lying between them, must then share.
248 monotone_rational_via_floats(x, prec, rm, asinh_prec_round_normal_ref)
249}
250
251impl Float {
252 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
253 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
254 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded inverse
255 /// hyperbolic sine is less than, equal to, or greater than the exact inverse hyperbolic sine.
256 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
257 /// it also returns `Equal`.
258 ///
259 /// See [`RoundingMode`] for a description of the possible rounding modes.
260 ///
261 /// $$
262 /// f(x,p,m) = \operatorname{asinh} x+\varepsilon.
263 /// $$
264 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
265 /// - If $x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
266 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p+1}$.
267 /// - If $x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
268 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$.
269 ///
270 /// If the output has a precision, it is `prec`.
271 ///
272 /// Special cases:
273 /// - $f(\text{NaN},p,m)=\text{NaN}$
274 /// - $f(\pm\infty,p,m)=\pm\infty$
275 /// - $f(\pm0.0,p,m)=\pm0.0$
276 ///
277 /// Overflow and underflow:
278 /// - Since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, the result never overflows.
279 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
280 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
281 /// instead.
282 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
283 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
284 /// instead.
285 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
286 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
287 /// instead.
288 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
289 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
290 /// returned instead.
291 ///
292 /// Underflow requires an input of magnitude $2^{-2^{30}}$, the smallest positive [`Float`],
293 /// rounded toward zero: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no other input
294 /// can reach it.
295 ///
296 /// If you know you'll be using `Nearest`, consider using [`Float::asinh_prec`] instead. If you
297 /// know that your target precision is the precision of the input, consider using
298 /// [`Float::asinh_round`] instead. If both of these things are true, consider using
299 /// [`Float::asinh`] instead.
300 ///
301 /// # Worst-case complexity
302 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
303 ///
304 /// $M(n, m) = O(n \log n + m \log m)$
305 ///
306 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
307 /// `self.significant_bits()`: the logarithm is computed at a working precision of about $n$,
308 /// and the input is first squared at its own precision.
309 ///
310 /// # Panics
311 /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the inverse hyperbolic
312 /// sine of a finite nonzero [`Float`] is never exactly representable, or if `prec` is zero.
313 ///
314 /// # Examples
315 /// ```
316 /// use malachite_base::rounding_modes::RoundingMode::*;
317 /// use malachite_float::Float;
318 /// use std::cmp::Ordering::*;
319 ///
320 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
321 /// .0
322 /// .asinh_prec_round(5, Floor);
323 /// assert_eq!(c.to_string(), "0.875");
324 /// assert_eq!(o, Less);
325 ///
326 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
327 /// .0
328 /// .asinh_prec_round(5, Ceiling);
329 /// assert_eq!(c.to_string(), "0.906");
330 /// assert_eq!(o, Greater);
331 ///
332 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
333 /// .0
334 /// .asinh_prec_round(5, Nearest);
335 /// assert_eq!(c.to_string(), "0.875");
336 /// assert_eq!(o, Less);
337 ///
338 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
339 /// .0
340 /// .asinh_prec_round(20, Floor);
341 /// assert_eq!(c.to_string(), "0.88137341");
342 /// assert_eq!(o, Less);
343 ///
344 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
345 /// .0
346 /// .asinh_prec_round(20, Ceiling);
347 /// assert_eq!(c.to_string(), "0.88137436");
348 /// assert_eq!(o, Greater);
349 ///
350 /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
351 /// .0
352 /// .asinh_prec_round(20, Nearest);
353 /// assert_eq!(c.to_string(), "0.88137341");
354 /// assert_eq!(o, Less);
355 /// ```
356 #[inline]
357 pub fn asinh_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
358 self.asinh_prec_round_ref(prec, rm)
359 }
360
361 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
362 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
363 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded inverse
364 /// hyperbolic sine is less than, equal to, or greater than the exact inverse hyperbolic sine.
365 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
366 /// it also returns `Equal`.
367 ///
368 /// See [`RoundingMode`] for a description of the possible rounding modes.
369 ///
370 /// $$
371 /// f(x,p,m) = \operatorname{asinh} x+\varepsilon.
372 /// $$
373 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
374 /// - If $x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
375 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p+1}$.
376 /// - If $x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
377 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$.
378 ///
379 /// If the output has a precision, it is `prec`.
380 ///
381 /// Special cases:
382 /// - $f(\text{NaN},p,m)=\text{NaN}$
383 /// - $f(\pm\infty,p,m)=\pm\infty$
384 /// - $f(\pm0.0,p,m)=\pm0.0$
385 ///
386 /// Overflow and underflow:
387 /// - Since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, the result never overflows.
388 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
389 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
390 /// instead.
391 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
392 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
393 /// instead.
394 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
395 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
396 /// instead.
397 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
398 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
399 /// returned instead.
400 ///
401 /// Underflow requires an input of magnitude $2^{-2^{30}}$, the smallest positive [`Float`],
402 /// rounded toward zero: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no other input
403 /// can reach it.
404 ///
405 /// If you know you'll be using `Nearest`, consider using [`Float::asinh_prec_ref`] instead. If
406 /// you know that your target precision is the precision of the input, consider using
407 /// [`Float::asinh_round_ref`] instead. If both of these things are true, consider using
408 /// `(&Float).asinh()` instead.
409 ///
410 /// # Worst-case complexity
411 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
412 ///
413 /// $M(n, m) = O(n \log n + m \log m)$
414 ///
415 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
416 /// `self.significant_bits()`: the logarithm is computed at a working precision of about $n$,
417 /// and the input is first squared at its own precision.
418 ///
419 /// # Panics
420 /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the inverse hyperbolic
421 /// sine of a finite nonzero [`Float`] is never exactly representable, or if `prec` is zero.
422 ///
423 /// # Examples
424 /// ```
425 /// use malachite_base::rounding_modes::RoundingMode::*;
426 /// use malachite_float::Float;
427 /// use std::cmp::Ordering::*;
428 ///
429 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_round_ref(5, Floor);
430 /// assert_eq!(c.to_string(), "0.875");
431 /// assert_eq!(o, Less);
432 ///
433 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_round_ref(5, Ceiling);
434 /// assert_eq!(c.to_string(), "0.906");
435 /// assert_eq!(o, Greater);
436 ///
437 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_round_ref(5, Nearest);
438 /// assert_eq!(c.to_string(), "0.875");
439 /// assert_eq!(o, Less);
440 ///
441 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_round_ref(20, Floor);
442 /// assert_eq!(c.to_string(), "0.88137341");
443 /// assert_eq!(o, Less);
444 ///
445 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_round_ref(20, Ceiling);
446 /// assert_eq!(c.to_string(), "0.88137436");
447 /// assert_eq!(o, Greater);
448 ///
449 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_round_ref(20, Nearest);
450 /// assert_eq!(c.to_string(), "0.88137341");
451 /// assert_eq!(o, Less);
452 /// ```
453 pub fn asinh_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
454 assert_ne!(prec, 0);
455 match &self.0 {
456 NaN => (Self::NAN, Equal),
457 // asinh(±inf) = ±inf, and asinh(±0) = ±0
458 Infinity { .. } | Zero { .. } => (self.clone(), Equal),
459 Finite { .. } => asinh_prec_round_normal_ref(self, prec, rm),
460 }
461 }
462
463 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
464 /// result to the nearest value of the specified precision. The [`Float`] is taken by value. An
465 /// [`Ordering`] is also returned, indicating whether the rounded inverse hyperbolic sine is
466 /// less than, equal to, or greater than the exact inverse hyperbolic sine. Although `NaN`s are
467 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
468 /// `Equal`.
469 ///
470 /// If the inverse hyperbolic sine is equidistant from two [`Float`]s with the specified
471 /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
472 /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
473 ///
474 /// $$
475 /// f(x,p) = \operatorname{asinh} x+\varepsilon.
476 /// $$
477 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
478 /// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
479 /// x|\rfloor-p}$.
480 ///
481 /// If the output has a precision, it is `prec`.
482 ///
483 /// Special cases:
484 /// - $f(\text{NaN},p)=\text{NaN}$
485 /// - $f(\pm\infty,p)=\pm\infty$
486 /// - $f(\pm0.0,p)=1.0$
487 ///
488 /// Overflow and underflow:
489 /// - Since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, the result never overflows.
490 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
491 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
492 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
493 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
494 ///
495 /// Underflow requires an input of magnitude $2^{-2^{30}}$, the smallest positive [`Float`],
496 /// rounded toward zero: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no other input
497 /// can reach it.
498 ///
499 /// If you want to use a rounding mode other than `Nearest`, consider using
500 /// [`Float::asinh_prec_round`] instead. If you know that your target precision is the precision
501 /// of the input, consider using [`Float::asinh`] instead.
502 ///
503 /// # Worst-case complexity
504 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
505 ///
506 /// $M(n, m) = O(n \log n + m \log m)$
507 ///
508 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
509 /// `self.significant_bits()`: the logarithm is computed at a working precision of about $n$,
510 /// and the input is first squared at its own precision.
511 ///
512 /// # Panics
513 /// Panics if `prec` is zero.
514 ///
515 /// # Examples
516 /// ```
517 /// use malachite_float::Float;
518 /// use std::cmp::Ordering::*;
519 ///
520 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.asinh_prec(5);
521 /// assert_eq!(c.to_string(), "0.875");
522 /// assert_eq!(o, Less);
523 ///
524 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.asinh_prec(20);
525 /// assert_eq!(c.to_string(), "0.88137341");
526 /// assert_eq!(o, Less);
527 /// ```
528 #[inline]
529 pub fn asinh_prec(self, prec: u64) -> (Self, Ordering) {
530 self.asinh_prec_round(prec, Nearest)
531 }
532
533 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
534 /// result to the nearest value of the specified precision. The [`Float`] is taken by reference.
535 /// An [`Ordering`] is also returned, indicating whether the rounded inverse hyperbolic sine is
536 /// less than, equal to, or greater than the exact inverse hyperbolic sine. Although `NaN`s are
537 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
538 /// `Equal`.
539 ///
540 /// If the inverse hyperbolic sine is equidistant from two [`Float`]s with the specified
541 /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
542 /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
543 ///
544 /// $$
545 /// f(x,p) = \operatorname{asinh} x+\varepsilon.
546 /// $$
547 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
548 /// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
549 /// x|\rfloor-p}$.
550 ///
551 /// If the output has a precision, it is `prec`.
552 ///
553 /// Special cases:
554 /// - $f(\text{NaN},p)=\text{NaN}$
555 /// - $f(\pm\infty,p)=\pm\infty$
556 /// - $f(\pm0.0,p)=1.0$
557 ///
558 /// Overflow and underflow:
559 /// - Since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, the result never overflows.
560 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
561 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
562 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
563 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
564 ///
565 /// Underflow requires an input of magnitude $2^{-2^{30}}$, the smallest positive [`Float`],
566 /// rounded toward zero: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no other input
567 /// can reach it.
568 ///
569 /// If you want to use a rounding mode other than `Nearest`, consider using
570 /// [`Float::asinh_prec_round_ref`] instead. If you know that your target precision is the
571 /// precision of the input, consider using `(&Float).asinh()` instead.
572 ///
573 /// # Worst-case complexity
574 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
575 ///
576 /// $M(n, m) = O(n \log n + m \log m)$
577 ///
578 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
579 /// `self.significant_bits()`: the logarithm is computed at a working precision of about $n$,
580 /// and the input is first squared at its own precision.
581 ///
582 /// # Panics
583 /// Panics if `prec` is zero.
584 ///
585 /// # Examples
586 /// ```
587 /// use malachite_float::Float;
588 /// use std::cmp::Ordering::*;
589 ///
590 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_ref(5);
591 /// assert_eq!(c.to_string(), "0.875");
592 /// assert_eq!(o, Less);
593 ///
594 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_prec_ref(20);
595 /// assert_eq!(c.to_string(), "0.88137341");
596 /// assert_eq!(o, Less);
597 /// ```
598 #[inline]
599 pub fn asinh_prec_ref(&self, prec: u64) -> (Self, Ordering) {
600 self.asinh_prec_round_ref(prec, Nearest)
601 }
602
603 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
604 /// result with the specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is
605 /// also returned, indicating whether the rounded inverse hyperbolic sine is less than, equal
606 /// to, or greater than the exact inverse hyperbolic sine. Although `NaN`s are not comparable to
607 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
608 ///
609 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
610 /// description of the possible rounding modes.
611 ///
612 /// $$
613 /// f(x,m) = \operatorname{asinh} x+\varepsilon.
614 /// $$
615 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
616 /// - If $x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
617 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p+1}$, where $p$ is the precision of the
618 /// input.
619 /// - If $x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
620 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$, where $p$ is the precision of the
621 /// input.
622 ///
623 /// If the output has a precision, it is the precision of the input.
624 ///
625 /// Special cases:
626 /// - $f(\text{NaN},m)=\text{NaN}$
627 /// - $f(\pm\infty,m)=\pm\infty$
628 /// - $f(\pm0.0,m)=1.0$
629 ///
630 /// Overflow and underflow:
631 /// - Since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, the result never overflows.
632 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
633 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
634 /// instead.
635 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
636 /// - If $2^{-2^{30}-1}<f(x,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
637 /// instead.
638 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
639 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
640 /// instead.
641 /// - If $-2^{-2^{30}-1}\leq f(x,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
642 /// - If $-2^{-2^{30}}<f(x,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is returned
643 /// instead.
644 ///
645 /// Underflow requires an input of magnitude $2^{-2^{30}}$, the smallest positive [`Float`],
646 /// rounded toward zero: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no other input
647 /// can reach it.
648 ///
649 /// If you want to specify an output precision, consider using [`Float::asinh_prec_round`]
650 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
651 /// [`Float::asinh`] instead.
652 ///
653 /// # Worst-case complexity
654 /// $T(n) = O(n (\log n)^2 \log\log n)$
655 ///
656 /// $M(n) = O(n \log n)$
657 ///
658 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
659 ///
660 /// # Panics
661 /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the inverse hyperbolic
662 /// sine of a finite nonzero [`Float`] is never exactly representable.
663 ///
664 /// # Examples
665 /// ```
666 /// use malachite_base::rounding_modes::RoundingMode::*;
667 /// use malachite_float::Float;
668 /// use std::cmp::Ordering::*;
669 ///
670 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.asinh_round(Floor);
671 /// assert_eq!(c.to_string(), "0.88137358701954302523260932497968");
672 /// assert_eq!(o, Less);
673 ///
674 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.asinh_round(Ceiling);
675 /// assert_eq!(c.to_string(), "0.88137358701954302523260932498047");
676 /// assert_eq!(o, Greater);
677 ///
678 /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.asinh_round(Nearest);
679 /// assert_eq!(c.to_string(), "0.88137358701954302523260932497968");
680 /// assert_eq!(o, Less);
681 /// ```
682 #[inline]
683 pub fn asinh_round(self, rm: RoundingMode) -> (Self, Ordering) {
684 let prec = self.significant_bits();
685 self.asinh_prec_round(prec, rm)
686 }
687
688 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
689 /// result with the specified rounding mode. The [`Float`] is taken by reference. An
690 /// [`Ordering`] is also returned, indicating whether the rounded inverse hyperbolic sine is
691 /// less than, equal to, or greater than the exact inverse hyperbolic sine. Although `NaN`s are
692 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
693 /// `Equal`.
694 ///
695 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
696 /// description of the possible rounding modes.
697 ///
698 /// $$
699 /// f(x,m) = \operatorname{asinh} x+\varepsilon.
700 /// $$
701 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
702 /// - If $x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
703 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p+1}$, where $p$ is the precision of the
704 /// input.
705 /// - If $x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
706 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$, where $p$ is the precision of the
707 /// input.
708 ///
709 /// If the output has a precision, it is the precision of the input.
710 ///
711 /// Special cases:
712 /// - $f(\text{NaN},m)=\text{NaN}$
713 /// - $f(\pm\infty,m)=\pm\infty$
714 /// - $f(\pm0.0,m)=1.0$
715 ///
716 /// Overflow and underflow:
717 /// - Since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, the result never overflows.
718 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
719 /// - If $0<f(x,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
720 /// instead.
721 /// - If $0<f(x,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
722 /// - If $2^{-2^{30}-1}<f(x,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
723 /// instead.
724 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
725 /// - If $-2^{-2^{30}}<f(x,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
726 /// instead.
727 /// - If $-2^{-2^{30}-1}\leq f(x,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
728 /// - If $-2^{-2^{30}}<f(x,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is returned
729 /// instead.
730 ///
731 /// Underflow requires an input of magnitude $2^{-2^{30}}$, the smallest positive [`Float`],
732 /// rounded toward zero: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no other input
733 /// can reach it.
734 ///
735 /// If you want to specify an output precision, consider using [`Float::asinh_prec_round_ref`]
736 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
737 /// `(&Float).asinh()` instead.
738 ///
739 /// # Worst-case complexity
740 /// $T(n) = O(n (\log n)^2 \log\log n)$
741 ///
742 /// $M(n) = O(n \log n)$
743 ///
744 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
745 ///
746 /// # Panics
747 /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the inverse hyperbolic
748 /// sine of a finite nonzero [`Float`] is never exactly representable.
749 ///
750 /// # Examples
751 /// ```
752 /// use malachite_base::rounding_modes::RoundingMode::*;
753 /// use malachite_float::Float;
754 /// use std::cmp::Ordering::*;
755 ///
756 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_round_ref(Floor);
757 /// assert_eq!(c.to_string(), "0.88137358701954302523260932497968");
758 /// assert_eq!(o, Less);
759 ///
760 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_round_ref(Ceiling);
761 /// assert_eq!(c.to_string(), "0.88137358701954302523260932498047");
762 /// assert_eq!(o, Greater);
763 ///
764 /// let (c, o) = (&Float::from_unsigned_prec(1u32, 100).0).asinh_round_ref(Nearest);
765 /// assert_eq!(c.to_string(), "0.88137358701954302523260932497968");
766 /// assert_eq!(o, Less);
767 /// ```
768 #[inline]
769 pub fn asinh_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
770 self.asinh_prec_round_ref(self.significant_bits(), rm)
771 }
772
773 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
774 /// result to the specified precision and with the specified rounding mode. The [`Float`] is
775 /// replaced by the result, and an [`Ordering`] is returned, indicating whether the rounded
776 /// inverse hyperbolic sine is less than, equal to, or greater than the exact inverse hyperbolic
777 /// sine. Although `NaN`s are not comparable to any [`Float`], whenever this function sets a
778 /// `NaN` it also returns `Equal`.
779 ///
780 /// See [`RoundingMode`] for a description of the possible rounding modes.
781 ///
782 /// $$
783 /// x \gets \operatorname{asinh} x+\varepsilon.
784 /// $$
785 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
786 /// - If $x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
787 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p+1}$.
788 /// - If $x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
789 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$.
790 ///
791 /// If the output has a precision, it is `prec`.
792 ///
793 /// See the [`Float::asinh_prec_round`] documentation for information on special cases,
794 /// overflow, and underflow.
795 ///
796 /// If you know you'll be using `Nearest`, consider using [`Float::asinh_prec_assign`] instead.
797 /// If you know that your target precision is the precision of the input, consider using
798 /// [`Float::asinh_round_assign`] instead. If both of these things are true, consider using
799 /// [`Float::asinh_assign`] instead.
800 ///
801 /// # Worst-case complexity
802 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
803 ///
804 /// $M(n, m) = O(n \log n + m \log m)$
805 ///
806 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
807 /// `self.significant_bits()`: the logarithm is computed at a working precision of about $n$,
808 /// and the input is first squared at its own precision.
809 ///
810 /// # Panics
811 /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the inverse hyperbolic
812 /// sine of a finite nonzero [`Float`] is never exactly representable, or if `prec` is zero.
813 ///
814 /// # Examples
815 /// ```
816 /// use malachite_base::rounding_modes::RoundingMode::*;
817 /// use malachite_float::Float;
818 /// use std::cmp::Ordering::*;
819 ///
820 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
821 /// assert_eq!(x.asinh_prec_round_assign(5, Floor), Less);
822 /// assert_eq!(x.to_string(), "0.875");
823 ///
824 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
825 /// assert_eq!(x.asinh_prec_round_assign(5, Ceiling), Greater);
826 /// assert_eq!(x.to_string(), "0.906");
827 ///
828 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
829 /// assert_eq!(x.asinh_prec_round_assign(5, Nearest), Less);
830 /// assert_eq!(x.to_string(), "0.875");
831 ///
832 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
833 /// assert_eq!(x.asinh_prec_round_assign(20, Floor), Less);
834 /// assert_eq!(x.to_string(), "0.88137341");
835 ///
836 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
837 /// assert_eq!(x.asinh_prec_round_assign(20, Ceiling), Greater);
838 /// assert_eq!(x.to_string(), "0.88137436");
839 ///
840 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
841 /// assert_eq!(x.asinh_prec_round_assign(20, Nearest), Less);
842 /// assert_eq!(x.to_string(), "0.88137341");
843 /// ```
844 #[inline]
845 pub fn asinh_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
846 let o;
847 (*self, o) = self.asinh_prec_round_ref(prec, rm);
848 o
849 }
850
851 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
852 /// result to the nearest value of the specified precision. The [`Float`] is replaced by the
853 /// result, and an [`Ordering`] is returned, indicating whether the rounded inverse hyperbolic
854 /// sine is less than, equal to, or greater than the exact inverse hyperbolic sine. Although
855 /// `NaN`s are not comparable to any [`Float`], whenever this function sets a `NaN` it also
856 /// returns `Equal`.
857 ///
858 /// If the inverse hyperbolic sine is equidistant from two [`Float`]s with the specified
859 /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
860 /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
861 ///
862 /// $$
863 /// x \gets \operatorname{asinh} x+\varepsilon.
864 /// $$
865 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
866 /// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
867 /// x|\rfloor-p}$.
868 ///
869 /// If the output has a precision, it is `prec`.
870 ///
871 /// See the [`Float::asinh_prec`] documentation for information on special cases, overflow, and
872 /// underflow.
873 ///
874 /// If you want to use a rounding mode other than `Nearest`, consider using
875 /// [`Float::asinh_prec_round_assign`] instead. If you know that your target precision is the
876 /// precision of the input, consider using [`Float::asinh_assign`] instead.
877 ///
878 /// # Worst-case complexity
879 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
880 ///
881 /// $M(n, m) = O(n \log n + m \log m)$
882 ///
883 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
884 /// `self.significant_bits()`: the logarithm is computed at a working precision of about $n$,
885 /// and the input is first squared at its own precision.
886 ///
887 /// # Panics
888 /// Panics if `prec` is zero.
889 ///
890 /// # Examples
891 /// ```
892 /// use malachite_float::Float;
893 /// use std::cmp::Ordering::*;
894 ///
895 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
896 /// assert_eq!(x.asinh_prec_assign(5), Less);
897 /// assert_eq!(x.to_string(), "0.875");
898 ///
899 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
900 /// assert_eq!(x.asinh_prec_assign(20), Less);
901 /// assert_eq!(x.to_string(), "0.88137341");
902 /// ```
903 #[inline]
904 pub fn asinh_prec_assign(&mut self, prec: u64) -> Ordering {
905 self.asinh_prec_round_assign(prec, Nearest)
906 }
907
908 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], rounding the
909 /// result with the specified rounding mode. The [`Float`] is replaced by the result, and an
910 /// [`Ordering`] is returned, indicating whether the rounded inverse hyperbolic sine is less
911 /// than, equal to, or greater than the exact inverse hyperbolic sine. Although `NaN`s are not
912 /// comparable to any [`Float`], whenever this function sets a `NaN` it also returns `Equal`.
913 ///
914 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
915 /// description of the possible rounding modes.
916 ///
917 /// $$
918 /// x \gets \operatorname{asinh} x+\varepsilon.
919 /// $$
920 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
921 /// - If $x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
922 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p+1}$, where $p$ is the precision of the
923 /// input.
924 /// - If $x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
925 /// 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$, where $p$ is the precision of the
926 /// input.
927 ///
928 /// If the output has a precision, it is the precision of the input.
929 ///
930 /// See the [`Float::asinh_round`] documentation for information on special cases, overflow, and
931 /// underflow.
932 ///
933 /// If you want to specify an output precision, consider using
934 /// [`Float::asinh_prec_round_assign`] instead. If you know you'll be using the `Nearest`
935 /// rounding mode, consider using [`Float::asinh_assign`] instead.
936 ///
937 /// # Worst-case complexity
938 /// $T(n) = O(n (\log n)^2 \log\log n)$
939 ///
940 /// $M(n) = O(n \log n)$
941 ///
942 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
943 ///
944 /// # Panics
945 /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the inverse hyperbolic
946 /// sine of a finite nonzero [`Float`] is never exactly representable.
947 ///
948 /// # Examples
949 /// ```
950 /// use malachite_base::rounding_modes::RoundingMode::*;
951 /// use malachite_float::Float;
952 /// use std::cmp::Ordering::*;
953 ///
954 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
955 /// assert_eq!(x.asinh_round_assign(Floor), Less);
956 /// assert_eq!(x.to_string(), "0.88137358701954302523260932497968");
957 ///
958 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
959 /// assert_eq!(x.asinh_round_assign(Ceiling), Greater);
960 /// assert_eq!(x.to_string(), "0.88137358701954302523260932498047");
961 ///
962 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
963 /// assert_eq!(x.asinh_round_assign(Nearest), Less);
964 /// assert_eq!(x.to_string(), "0.88137358701954302523260932497968");
965 /// ```
966 #[inline]
967 pub fn asinh_round_assign(&mut self, rm: RoundingMode) -> Ordering {
968 let prec = self.significant_bits();
969 self.asinh_prec_round_assign(prec, rm)
970 }
971}
972
973impl Float {
974 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Rational`], rounding
975 /// the result to the specified precision and with the specified rounding mode and returning the
976 /// result as a [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned,
977 /// indicating whether the rounded inverse hyperbolic sine is less than, equal to, or greater
978 /// than the exact inverse hyperbolic sine.
979 ///
980 /// See [`RoundingMode`] for a description of the possible rounding modes.
981 ///
982 /// $$
983 /// f(x,p,m) = \operatorname{asinh} x+\varepsilon.
984 /// $$
985 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
986 /// x|\rfloor-p+1}$.
987 /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\operatorname{asinh}
988 /// x|\rfloor-p}$.
989 ///
990 /// These bounds do not apply when the result overflows or underflows; see below.
991 ///
992 /// The output has precision `prec`.
993 ///
994 /// Special cases:
995 /// - $f(0,p,m)=0.0$.
996 ///
997 /// Overflow and underflow:
998 /// - Since $|\operatorname{asinh} x| < \ln(2|x|+1)$, the result never overflows.
999 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1000 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1001 /// instead.
1002 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1003 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1004 /// instead.
1005 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1006 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1007 /// instead.
1008 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1009 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1010 /// returned instead.
1011 ///
1012 /// Underflow requires an input of magnitude at most $2^{-2^{30}}$, the smallest positive
1013 /// [`Float`]: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no larger input can reach
1014 /// it.
1015 ///
1016 /// If you know you'll be using `Nearest`, consider using [`Float::asinh_rational_prec`]
1017 /// 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, or if `rm` is `Exact` but the result cannot be represented exactly
1030 /// with the given precision (which is the case for every nonzero input).
1031 ///
1032 /// # Examples
1033 /// ```
1034 /// use malachite_base::rounding_modes::RoundingMode::*;
1035 /// use malachite_float::Float;
1036 /// use malachite_q::Rational;
1037 /// use std::cmp::Ordering::*;
1038 ///
1039 /// let (c, o) = Float::asinh_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor);
1040 /// assert_eq!(c.to_string(), "0.562");
1041 /// assert_eq!(o, Less);
1042 ///
1043 /// let (c, o) = Float::asinh_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1044 /// assert_eq!(c.to_string(), "0.594");
1045 /// assert_eq!(o, Greater);
1046 ///
1047 /// let (c, o) = Float::asinh_rational_prec_round(Rational::from_signeds(-3i8, 5), 20, Floor);
1048 /// assert_eq!(c.to_string(), "-0.56882572");
1049 /// assert_eq!(o, Less);
1050 ///
1051 /// let (c, o) = Float::asinh_rational_prec_round(Rational::from_signeds(-3i8, 5), 20, Ceiling);
1052 /// assert_eq!(c.to_string(), "-0.56882477");
1053 /// assert_eq!(o, Greater);
1054 /// ```
1055 #[inline]
1056 #[allow(clippy::needless_pass_by_value)]
1057 pub fn asinh_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
1058 Self::asinh_rational_prec_round_ref(&x, prec, rm)
1059 }
1060
1061 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Rational`], rounding
1062 /// the result to the specified precision and with the specified rounding mode and returning the
1063 /// result as a [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also
1064 /// returned, indicating whether the rounded inverse hyperbolic sine is less than, equal to, or
1065 /// greater than the exact inverse hyperbolic sine.
1066 ///
1067 /// See [`RoundingMode`] for a description of the possible rounding modes.
1068 ///
1069 /// $$
1070 /// f(x,p,m) = \operatorname{asinh} x+\varepsilon.
1071 /// $$
1072 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
1073 /// x|\rfloor-p+1}$.
1074 /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\operatorname{asinh}
1075 /// x|\rfloor-p}$.
1076 ///
1077 /// These bounds do not apply when the result overflows or underflows; see below.
1078 ///
1079 /// The output has precision `prec`.
1080 ///
1081 /// Special cases:
1082 /// - $f(0,p,m)=0.0$.
1083 ///
1084 /// Overflow and underflow:
1085 /// - Since $|\operatorname{asinh} x| < \ln(2|x|+1)$, the result never overflows.
1086 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1087 /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1088 /// instead.
1089 /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1090 /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1091 /// instead.
1092 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1093 /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1094 /// instead.
1095 /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1096 /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1097 /// returned instead.
1098 ///
1099 /// Underflow requires an input of magnitude at most $2^{-2^{30}}$, the smallest positive
1100 /// [`Float`]: since $|\operatorname{asinh} x| < |x|$ for nonzero $x$, no larger input can reach
1101 /// it.
1102 ///
1103 /// If you know you'll be using `Nearest`, consider using [`Float::asinh_rational_prec_ref`]
1104 /// instead.
1105 ///
1106 /// # Worst-case complexity
1107 /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
1108 ///
1109 /// $M(n, m) = O(n \log n + m \log m)$
1110 ///
1111 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1112 /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
1113 /// the input is handled with `Rational` arithmetic.
1114 ///
1115 /// # Panics
1116 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1117 /// with the given precision (which is the case for every nonzero input).
1118 ///
1119 /// # Examples
1120 /// ```
1121 /// use malachite_base::rounding_modes::RoundingMode::*;
1122 /// use malachite_float::Float;
1123 /// use malachite_q::Rational;
1124 /// use std::cmp::Ordering::*;
1125 ///
1126 /// let (c, o) =
1127 /// Float::asinh_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Floor);
1128 /// assert_eq!(c.to_string(), "0.562");
1129 /// assert_eq!(o, Less);
1130 ///
1131 /// let (c, o) =
1132 /// Float::asinh_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1133 /// assert_eq!(c.to_string(), "0.594");
1134 /// assert_eq!(o, Greater);
1135 ///
1136 /// let (c, o) =
1137 /// Float::asinh_rational_prec_round_ref(&Rational::from_signeds(-3i8, 5), 20, Floor);
1138 /// assert_eq!(c.to_string(), "-0.56882572");
1139 /// assert_eq!(o, Less);
1140 ///
1141 /// let (c, o) =
1142 /// Float::asinh_rational_prec_round_ref(&Rational::from_signeds(-3i8, 5), 20, Ceiling);
1143 /// assert_eq!(c.to_string(), "-0.56882477");
1144 /// assert_eq!(o, Greater);
1145 /// ```
1146 pub fn asinh_rational_prec_round_ref(
1147 x: &Rational,
1148 prec: u64,
1149 rm: RoundingMode,
1150 ) -> (Self, Ordering) {
1151 assert_ne!(prec, 0);
1152 if *x == 0u32 {
1153 // asinh(0) = 0, exactly
1154 return (Self::ZERO, Equal);
1155 }
1156 asinh_rational_helper(x, prec, rm)
1157 }
1158
1159 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Rational`], rounding
1160 /// the result to the nearest value of the specified precision and returning the result as a
1161 /// [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating
1162 /// whether the rounded inverse hyperbolic sine is less than, equal to, or greater than the
1163 /// exact inverse hyperbolic sine.
1164 ///
1165 /// If the inverse hyperbolic sine is equidistant from two [`Float`]s with the specified
1166 /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
1167 /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
1168 ///
1169 /// $$
1170 /// f(x,p) = \operatorname{asinh} x+\varepsilon,
1171 /// $$
1172 /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$ (unless the
1173 /// result overflows or underflows; see below).
1174 ///
1175 /// The output has precision `prec`.
1176 ///
1177 /// Special cases:
1178 /// - $f(0,p)=0.0$.
1179 ///
1180 /// Overflow and underflow:
1181 /// - Since $|\operatorname{asinh} x| < \ln(2|x|+1)$, the result never overflows.
1182 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1183 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1184 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1185 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1186 ///
1187 /// If you want to use a rounding mode other than `Nearest`, consider using
1188 /// [`Float::asinh_rational_prec_round`] instead.
1189 ///
1190 /// # Worst-case complexity
1191 /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
1192 ///
1193 /// $M(n, m) = O(n \log n + m \log m)$
1194 ///
1195 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1196 /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
1197 /// the input is handled with `Rational` arithmetic.
1198 ///
1199 /// # Panics
1200 /// Panics if `prec` is zero.
1201 ///
1202 /// # Examples
1203 /// ```
1204 /// use malachite_base::num::basic::traits::Zero;
1205 /// use malachite_float::Float;
1206 /// use malachite_q::Rational;
1207 /// use std::cmp::Ordering::*;
1208 ///
1209 /// let (c, o) = Float::asinh_rational_prec(Rational::from_unsigneds(3u8, 5), 5);
1210 /// assert_eq!(c.to_string(), "0.562");
1211 /// assert_eq!(o, Less);
1212 ///
1213 /// let (c, o) = Float::asinh_rational_prec(Rational::from_unsigneds(3u8, 5), 20);
1214 /// assert_eq!(c.to_string(), "0.56882477");
1215 /// assert_eq!(o, Less);
1216 ///
1217 /// let (c, o) = Float::asinh_rational_prec(Rational::ZERO, 10);
1218 /// assert_eq!(c.to_string(), "0.0");
1219 /// assert_eq!(o, Equal);
1220 /// ```
1221 #[inline]
1222 #[allow(clippy::needless_pass_by_value)]
1223 pub fn asinh_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
1224 Self::asinh_rational_prec_round_ref(&x, prec, Nearest)
1225 }
1226
1227 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Rational`], rounding
1228 /// the result to the nearest value of the specified precision and returning the result as a
1229 /// [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also returned,
1230 /// indicating whether the rounded inverse hyperbolic sine is less than, equal to, or greater
1231 /// than the exact inverse hyperbolic sine.
1232 ///
1233 /// If the inverse hyperbolic sine is equidistant from two [`Float`]s with the specified
1234 /// precision, the [`Float`] with fewer 1s in its binary expansion is chosen. See
1235 /// [`RoundingMode`] for a description of the `Nearest` rounding mode.
1236 ///
1237 /// $$
1238 /// f(x,p) = \operatorname{asinh} x+\varepsilon,
1239 /// $$
1240 /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\operatorname{asinh} x|\rfloor-p}$ (unless the
1241 /// result overflows or underflows; see below).
1242 ///
1243 /// The output has precision `prec`.
1244 ///
1245 /// Special cases:
1246 /// - $f(0,p)=0.0$.
1247 ///
1248 /// Overflow and underflow:
1249 /// - Since $|\operatorname{asinh} x| < \ln(2|x|+1)$, the result never overflows.
1250 /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1251 /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1252 /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1253 /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1254 ///
1255 /// If you want to use a rounding mode other than `Nearest`, consider using
1256 /// [`Float::asinh_rational_prec_round_ref`] instead.
1257 ///
1258 /// # Worst-case complexity
1259 /// $T(n, m) = O(n (\log n)^2 \log\log n + m (\log m)^2 \log\log m)$
1260 ///
1261 /// $M(n, m) = O(n \log n + m \log m)$
1262 ///
1263 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1264 /// `x.significant_bits()`: the logarithm is computed at a working precision of about $n$, and
1265 /// the input is handled with `Rational` arithmetic.
1266 ///
1267 /// # Panics
1268 /// Panics if `prec` is zero.
1269 ///
1270 /// # Examples
1271 /// ```
1272 /// use malachite_base::num::basic::traits::Zero;
1273 /// use malachite_float::Float;
1274 /// use malachite_q::Rational;
1275 /// use std::cmp::Ordering::*;
1276 ///
1277 /// let (c, o) = Float::asinh_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 5);
1278 /// assert_eq!(c.to_string(), "0.562");
1279 /// assert_eq!(o, Less);
1280 ///
1281 /// let (c, o) = Float::asinh_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 20);
1282 /// assert_eq!(c.to_string(), "0.56882477");
1283 /// assert_eq!(o, Less);
1284 ///
1285 /// let (c, o) = Float::asinh_rational_prec_ref(&Rational::ZERO, 10);
1286 /// assert_eq!(c.to_string(), "0.0");
1287 /// assert_eq!(o, Equal);
1288 /// ```
1289 #[inline]
1290 pub fn asinh_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
1291 Self::asinh_rational_prec_round_ref(x, prec, Nearest)
1292 }
1293}
1294
1295impl Asinh for Float {
1296 type Output = Self;
1297
1298 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], taking it by
1299 /// value.
1300 ///
1301 /// If the output has a precision, it is the precision of the input. If the inverse hyperbolic
1302 /// sine is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
1303 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
1304 /// `Nearest` rounding mode.
1305 ///
1306 /// $$
1307 /// f(x) = \operatorname{asinh} x+\varepsilon.
1308 /// $$
1309 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
1310 /// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
1311 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1312 ///
1313 /// Special cases:
1314 /// - $f(\text{NaN})=\text{NaN}$
1315 /// - $f(\pm\infty)=\pm\infty$
1316 /// - $f(\pm0.0)=\pm0.0$
1317 ///
1318 /// See the [`Float::asinh_round`] documentation for information on overflow and underflow.
1319 ///
1320 /// If you want to use a rounding mode other than `Nearest`, consider using
1321 /// [`Float::asinh_round`] instead. If you want to specify the output precision, consider using
1322 /// [`Float::asinh_prec`]. If you want both of these things, consider using
1323 /// [`Float::asinh_prec_round`].
1324 ///
1325 /// # Worst-case complexity
1326 /// $T(n) = O(n (\log n)^2 \log\log n)$
1327 ///
1328 /// $M(n) = O(n \log n)$
1329 ///
1330 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1331 ///
1332 /// # Examples
1333 /// ```
1334 /// use malachite_base::num::arithmetic::traits::Asinh;
1335 /// use malachite_base::num::basic::traits::*;
1336 /// use malachite_float::Float;
1337 ///
1338 /// assert!(Float::NAN.asinh().is_nan());
1339 /// assert_eq!(Float::INFINITY.asinh().to_string(), "Infinity");
1340 /// assert_eq!(Float::NEGATIVE_INFINITY.asinh().to_string(), "-Infinity");
1341 /// assert_eq!(Float::ZERO.asinh().to_string(), "0.0");
1342 /// assert_eq!(Float::NEGATIVE_ZERO.asinh().to_string(), "-0.0");
1343 /// assert_eq!(
1344 /// Float::from_unsigned_prec(1u32, 100).0.asinh().to_string(),
1345 /// "0.88137358701954302523260932497968"
1346 /// );
1347 /// assert_eq!(
1348 /// Float::from_unsigned_prec(100u32, 100).0.asinh().to_string(),
1349 /// "5.2983423656105887573688256891151"
1350 /// );
1351 /// ```
1352 #[inline]
1353 fn asinh(self) -> Self {
1354 let prec = self.significant_bits();
1355 self.asinh_prec_round(prec, Nearest).0
1356 }
1357}
1358
1359impl Asinh for &Float {
1360 type Output = Float;
1361
1362 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], taking it by
1363 /// reference.
1364 ///
1365 /// If the output has a precision, it is the precision of the input. If the inverse hyperbolic
1366 /// sine is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
1367 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
1368 /// `Nearest` rounding mode.
1369 ///
1370 /// $$
1371 /// f(x) = \operatorname{asinh} x+\varepsilon.
1372 /// $$
1373 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
1374 /// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
1375 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1376 ///
1377 /// Special cases:
1378 /// - $f(\text{NaN})=\text{NaN}$
1379 /// - $f(\pm\infty)=\pm\infty$
1380 /// - $f(\pm0.0)=\pm0.0$
1381 ///
1382 /// See the [`Float::asinh_round`] documentation for information on overflow and underflow.
1383 ///
1384 /// If you want to use a rounding mode other than `Nearest`, consider using
1385 /// [`Float::asinh_round_ref`] instead. If you want to specify the output precision, consider
1386 /// using [`Float::asinh_prec_ref`]. If you want both of these things, consider using
1387 /// [`Float::asinh_prec_round_ref`].
1388 ///
1389 /// # Worst-case complexity
1390 /// $T(n) = O(n (\log n)^2 \log\log n)$
1391 ///
1392 /// $M(n) = O(n \log n)$
1393 ///
1394 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1395 ///
1396 /// # Examples
1397 /// ```
1398 /// use malachite_base::num::arithmetic::traits::Asinh;
1399 /// use malachite_base::num::basic::traits::*;
1400 /// use malachite_float::Float;
1401 ///
1402 /// assert!(Float::NAN.asinh().is_nan());
1403 /// assert_eq!(Float::INFINITY.asinh().to_string(), "Infinity");
1404 /// assert_eq!(Float::NEGATIVE_INFINITY.asinh().to_string(), "-Infinity");
1405 /// assert_eq!(Float::ZERO.asinh().to_string(), "0.0");
1406 /// assert_eq!(Float::NEGATIVE_ZERO.asinh().to_string(), "-0.0");
1407 /// assert_eq!(
1408 /// (&Float::from_unsigned_prec(1u32, 100).0)
1409 /// .asinh()
1410 /// .to_string(),
1411 /// "0.88137358701954302523260932497968"
1412 /// );
1413 /// assert_eq!(
1414 /// (&Float::from_unsigned_prec(100u32, 100).0)
1415 /// .asinh()
1416 /// .to_string(),
1417 /// "5.2983423656105887573688256891151"
1418 /// );
1419 /// ```
1420 #[inline]
1421 fn asinh(self) -> Float {
1422 self.asinh_prec_round_ref(self.significant_bits(), Nearest)
1423 .0
1424 }
1425}
1426
1427impl AsinhAssign for Float {
1428 /// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Float`], in place.
1429 ///
1430 /// If the output has a precision, it is the precision of the input. If the inverse hyperbolic
1431 /// sine is equidistant from two [`Float`]s with the specified precision, the [`Float`] with
1432 /// fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of the
1433 /// `Nearest` rounding mode.
1434 ///
1435 /// $$
1436 /// x \gets \operatorname{asinh} x+\varepsilon.
1437 /// $$
1438 /// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
1439 /// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
1440 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1441 ///
1442 /// See the [`Float::asinh`] documentation for information on special cases, overflow, and
1443 /// underflow.
1444 ///
1445 /// If you want to use a rounding mode other than `Nearest`, consider using
1446 /// [`Float::asinh_round_assign`] instead. If you want to specify the output precision, consider
1447 /// using [`Float::asinh_prec_assign`]. If you want both of these things, consider using
1448 /// [`Float::asinh_prec_round_assign`].
1449 ///
1450 /// # Worst-case complexity
1451 /// $T(n) = O(n (\log n)^2 \log\log n)$
1452 ///
1453 /// $M(n) = O(n \log n)$
1454 ///
1455 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1456 ///
1457 /// # Examples
1458 /// ```
1459 /// use malachite_base::num::arithmetic::traits::AsinhAssign;
1460 /// use malachite_base::num::basic::traits::*;
1461 /// use malachite_float::Float;
1462 ///
1463 /// let mut x = Float::NAN;
1464 /// x.asinh_assign();
1465 /// assert!(x.is_nan());
1466 ///
1467 /// let mut x = Float::INFINITY;
1468 /// x.asinh_assign();
1469 /// assert_eq!(x.to_string(), "Infinity");
1470 ///
1471 /// let mut x = Float::NEGATIVE_INFINITY;
1472 /// x.asinh_assign();
1473 /// assert_eq!(x.to_string(), "-Infinity");
1474 ///
1475 /// let mut x = Float::ZERO;
1476 /// x.asinh_assign();
1477 /// assert_eq!(x.to_string(), "0.0");
1478 ///
1479 /// let mut x = Float::NEGATIVE_ZERO;
1480 /// x.asinh_assign();
1481 /// assert_eq!(x.to_string(), "-0.0");
1482 ///
1483 /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1484 /// x.asinh_assign();
1485 /// assert_eq!(x.to_string(), "0.88137358701954302523260932497968");
1486 ///
1487 /// let mut x = Float::from_unsigned_prec(100u32, 100).0;
1488 /// x.asinh_assign();
1489 /// assert_eq!(x.to_string(), "5.2983423656105887573688256891151");
1490 /// ```
1491 #[inline]
1492 fn asinh_assign(&mut self) {
1493 let prec = self.significant_bits();
1494 self.asinh_prec_round_assign(prec, Nearest);
1495 }
1496}
1497
1498/// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a primitive float. Using this
1499/// function is more accurate than using the default `asinh` function or the one provided by `libm`.
1500///
1501/// $$
1502/// f(x) = \operatorname{asinh} x+\varepsilon.
1503/// $$
1504/// - If $x$ is infinite, zero, or NaN, $\varepsilon$ may be ignored or assumed to be 0.
1505/// - If $x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\operatorname{asinh}
1506/// x|\rfloor-p}$, where $p$ is the precision of the output (24 if `T` is a [`f32`] and 53 if `T`
1507/// is a [`f64`]).
1508///
1509/// Special cases:
1510/// - $f(\text{NaN})=\text{NaN}$
1511/// - $f(\pm\infty)=\pm\infty$
1512/// - $f(\pm0.0)=\pm0.0$
1513///
1514/// Overflow is not possible, since $|\operatorname{asinh} x| \leq |x|$. The result is subnormal
1515/// only when $x$ is, and then it is $x$ itself, since $|\operatorname{asinh} x - x| < |x|^3/6$.
1516///
1517/// # Worst-case complexity
1518/// Constant time and additional memory.
1519///
1520/// # Examples
1521/// ```
1522/// use malachite_base::num::basic::traits::NegativeInfinity;
1523/// use malachite_base::num::float::NiceFloat;
1524/// use malachite_float::float::arithmetic::asinh::primitive_float_asinh;
1525///
1526/// assert!(primitive_float_asinh(f32::NAN).is_nan());
1527/// assert_eq!(
1528/// NiceFloat(primitive_float_asinh(f32::INFINITY)),
1529/// NiceFloat(f32::INFINITY)
1530/// );
1531/// assert_eq!(
1532/// NiceFloat(primitive_float_asinh(f32::NEGATIVE_INFINITY)),
1533/// NiceFloat(f32::NEGATIVE_INFINITY)
1534/// );
1535/// assert_eq!(NiceFloat(primitive_float_asinh(0.0f32)), NiceFloat(0.0));
1536/// assert_eq!(NiceFloat(primitive_float_asinh(-0.0f32)), NiceFloat(-0.0));
1537/// assert_eq!(
1538/// NiceFloat(primitive_float_asinh(1.0f32)),
1539/// NiceFloat(0.8813736)
1540/// );
1541/// assert_eq!(
1542/// NiceFloat(primitive_float_asinh(1.0f64)),
1543/// NiceFloat(0.881373587019543)
1544/// );
1545/// ```
1546#[inline]
1547#[allow(clippy::type_repetition_in_bounds)]
1548pub fn primitive_float_asinh<T: PrimitiveFloat>(x: T) -> T
1549where
1550 Float: From<T> + PartialOrd<T>,
1551 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1552{
1553 emulate_float_to_float_fn(Float::asinh_prec, x)
1554}
1555
1556/// Computes $\operatorname{asinh} x$, the inverse hyperbolic sine of a [`Rational`], returning the
1557/// result as a primitive float. The result is correctly rounded.
1558///
1559/// $$
1560/// f(x) = \operatorname{asinh} x+\varepsilon.
1561/// $$
1562/// - If $\operatorname{asinh} x$ is infinite or zero, $\varepsilon$ may be ignored or assumed to be
1563/// 0.
1564/// - If $\operatorname{asinh} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1565/// |\operatorname{asinh} x|\rfloor-p}$, where $p$ is the precision of the output (typically 24 if
1566/// `T` is a [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
1567///
1568/// Special cases:
1569/// - $f(0)=0.0$
1570///
1571/// Overflow is not possible. Underflow is: an `x` of small enough magnitude gives `0.0` or `-0.0`.
1572///
1573/// # Worst-case complexity
1574/// $T(m) = O(m (\log m)^2 \log\log m)$
1575///
1576/// $M(m) = O(m \log m)$
1577///
1578/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`.
1579///
1580/// # Examples
1581/// ```
1582/// use malachite_base::num::basic::traits::Zero;
1583/// use malachite_base::num::float::NiceFloat;
1584/// use malachite_float::float::arithmetic::asinh::primitive_float_asinh_rational;
1585/// use malachite_q::Rational;
1586///
1587/// assert_eq!(
1588/// NiceFloat(primitive_float_asinh_rational::<f64>(&Rational::ZERO)),
1589/// NiceFloat(0.0)
1590/// );
1591/// assert_eq!(
1592/// NiceFloat(primitive_float_asinh_rational::<f64>(
1593/// &Rational::from_unsigneds(1u8, 3)
1594/// )),
1595/// NiceFloat(0.32745015023725843)
1596/// );
1597/// assert_eq!(
1598/// NiceFloat(primitive_float_asinh_rational::<f64>(
1599/// &Rational::from_unsigneds(22u8, 7)
1600/// )),
1601/// NiceFloat(1.86267921113461)
1602/// );
1603/// ```
1604#[inline]
1605#[allow(clippy::type_repetition_in_bounds)]
1606pub fn primitive_float_asinh_rational<T: PrimitiveFloat>(x: &Rational) -> T
1607where
1608 Float: PartialOrd<T>,
1609 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1610{
1611 emulate_rational_to_float_fn(Float::asinh_rational_prec_ref, x)
1612}