| @@ -1228,29 +1228,23 @@ template<typename T> real_t<T> erfc(real_t<T> const &x) | |||||
| template<typename T> real_t<T> sinh(real_t<T> const &x) | template<typename T> real_t<T> sinh(real_t<T> const &x) | ||||
| { | { | ||||
| /* We cannot always use (exp(x)-exp(-x))/2 because we'll lose | |||||
| * accuracy near zero. We only use this identity for |x|>0.5. If | |||||
| * |x|<=0.5, we compute exp(x)-1 and exp(-x)-1 instead. */ | |||||
| bool near_zero = (fabs(x) < real_t<T>::R_1() / 2); | |||||
| auto x1 = near_zero ? fast_exp_sub(x, real_t<T>::R_1()) : exp(x); | |||||
| auto x2 = near_zero ? fast_exp_sub(-x, real_t<T>::R_1()) : exp(-x); | |||||
| return (x1 - x2) / 2; | |||||
| // Use expm1() to ensure high accuracy around 0. No need to worry about | |||||
| // accuracy in other ranges because either exp(x) or exp(-x) will be | |||||
| // very large and cancel the other term. | |||||
| return (expm1(x) - expm1(-x)) / 2; | |||||
| } | } | ||||
| template<typename T> real_t<T> tanh(real_t<T> const &x) | template<typename T> real_t<T> tanh(real_t<T> const &x) | ||||
| { | { | ||||
| /* See sinh() for the strategy here */ | |||||
| bool near_zero = (fabs(x) < real_t<T>::R_1() / 2); | |||||
| auto x1 = near_zero ? fast_exp_sub(x, real_t<T>::R_1()) : exp(x); | |||||
| auto x2 = near_zero ? fast_exp_sub(-x, real_t<T>::R_1()) : exp(-x); | |||||
| auto x3 = near_zero ? x1 + x2 + real_t<T>::R_2() : x1 + x2; | |||||
| return (x1 - x2) / x3; | |||||
| // See sinh() for the strategy here. | |||||
| auto x1 = expm1(x), x2 = expm1(-x); | |||||
| return (x1 - x2) / (x1 + x2 + real_t<T>::R_2()); | |||||
| } | } | ||||
| template<typename T> real_t<T> cosh(real_t<T> const &x) | template<typename T> real_t<T> cosh(real_t<T> const &x) | ||||
| { | { | ||||
| /* No need to worry about accuracy here; maybe the last bit is slightly | |||||
| * off, but that's about it. */ | |||||
| // No need to worry about accuracy here; maybe the last bit is slightly | |||||
| // off, but that's about it. | |||||
| return (exp(x) + exp(-x)) / 2; | return (exp(x) + exp(-x)) / 2; | ||||
| } | } | ||||