Skip to main content

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