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}