Cosh(x) = (e^x + e^-x) / 2 = e^(x + log(1/2)) + e^(-x + log(1/2)). The second formulation avoids overflowing when e^x = inf but (e^x)/2 is not inf. This incorrectly overflows to inf for two f32 input values, namely +/-89.4159851, due to rounding error when computing x +/- log(1/2). The correct answer of 3.40281961e+38 (0x7f7fffec) is very close to max-float, so we deem this acceptable.
| 1260 | // correct answer of 3.40281961e+38 (0x7f7fffec) is very close to max-float, so |
| 1261 | // we deem this acceptable. |
| 1262 | XlaOp Cosh(XlaOp x) { |
| 1263 | return DoWithUpcastToF32(x, {BF16, F16}, [](XlaOp x) { |
| 1264 | auto log_one_half = Log(ScalarLike(x, 0.5)); |
| 1265 | return Exp(x + log_one_half) + Exp(-x + log_one_half); |
| 1266 | }); |
| 1267 | } |
| 1268 | |
| 1269 | // Sinh(x) = (e^x - e^-x) / 2 |
| 1270 | // = e^(x + log(1/2)) - e^(-x + log(1/2)). |