rustymath_core/
hyperbolic.rs1use crate::{float::Native, ln::ln_parts};
3
4#[inline]
6pub(crate) fn sinh<R: Native, const FUSED: bool>(x: R) -> R { sinh_formula(&crate::recipe::NativeOps::<FUSED>::DEFAULT, x) }
7#[inline]
8pub(crate) fn cosh<R: Native, const FUSED: bool>(x: R) -> R { cosh_formula(&crate::recipe::NativeOps::<FUSED>::DEFAULT, x) }
9#[inline]
10pub(crate) fn tanh<R: Native, const FUSED: bool>(x: R) -> R { tanh_formula(&crate::recipe::NativeOps::<FUSED>::DEFAULT, x) }
11
12#[inline]
13pub(crate) fn sinh_formula<F: crate::Float, O: crate::recipe::Ops<F> + ?Sized>(o: &O, x: O::V) -> O::V {
14 let one = o.number(F::one());
15 let h = crate::exp::minus_one_formula(o, o.magnitude(x), o.negate(one));
16 let result = o.multiply(h, o.add(one, o.divide(one, o.add(o.add(h, h), one))));
17 o.select(o.less(x, o.number(F::zero())), o.negate(result), result)
18}
19#[inline]
20pub(crate) fn cosh_formula<F: crate::Float, O: crate::recipe::Ops<F> + ?Sized>(o: &O, x: O::V) -> O::V {
21 let e = crate::exp::scaled_formula(o, o.magnitude(x), o.number(-F::one()));
22 o.add(e, o.divide(o.number(F::narrow(0.25)), e))
23}
24#[inline]
25pub(crate) fn tanh_formula<F: crate::Float, O: crate::recipe::Ops<F> + ?Sized>(o: &O, x: O::V) -> O::V {
26 let top = o.number(F::narrow(if o.width() == crate::buffer::FloatWidth::F64 { 20.0 } else { 9.0 }));
27 let a = o.magnitude(x);
28 let a = o.select(o.less(top, a), top, a);
29 let e = crate::exp::minus_one_formula(o, o.add(a, a), o.number(F::zero()));
30 let result = o.divide(e, o.add(e, o.number(F::narrow(2.0))));
31 o.select(o.less(x, o.number(F::zero())), o.negate(result), result)
32}
33
34#[inline]
36fn large<R: Native>() -> R { R::narrow(4503599627370496.0) }
37
38#[inline]
40fn ln_of<R: Native, const FUSED: bool>(v: R, far: bool, near: (R, R)) -> R {
41 let (m, e) = v.split();
42 let e = if far { e + R::one() } else { e };
43 let (num, den) = if e == R::zero() { near } else { (m - R::one(), m + R::one()) };
44 let y = ln_parts::<R, FUSED>(num / den, e);
45 if v.is_nan() | (v == R::infinity()) { v } else { y }
46}
47
48#[inline]
50pub(crate) fn asinh<R: Native, const FUSED: bool>(x: R) -> R {
51 let a = x.abs();
52 let far = a > large();
53 let r = a.mla::<FUSED>(a, R::one()).sqrt();
54 let (q, a2) = (R::one() + r, a * a);
55 let near = (a.mla::<FUSED>(q, a2), (a + R::narrow(2.0)).mla::<FUSED>(q, a2));
56 ln_of::<R, FUSED>(if far { a } else { a + r }, far, near).copysign(x)
57}
58
59#[inline]
61pub(crate) fn acosh<R: Native, const FUSED: bool>(x: R) -> R {
62 let far = x > large();
63 let d = x - R::one();
64 let t = d + d.mla::<FUSED>(d, d + d).sqrt();
65 let y = ln_of::<R, FUSED>(if far { x } else { R::one() + t }, far, (t, t + R::narrow(2.0)));
66 if x < R::one() { R::nan() } else { y }
67}
68
69#[inline]
71pub(crate) fn atanh<R: Native, const FUSED: bool>(x: R) -> R {
72 let a = x.abs();
73 let y = ln_of::<R, FUSED>((R::one() + a) / (R::one() - a), false, (a, R::one())) * R::narrow(0.5);
74 (if a <= R::one() { y } else { R::nan() }).copysign(x)
75}
76
77#[derive(Clone, Copy, Debug)]
79pub struct RealAcosh;
80
81#[derive(Clone, Copy, Debug)]
83pub struct RealAtanh;