acosh(x) = log(x + sqrt(x^2 - 1)) if x >= -1 = log(x + sqrt((x+1)*(x-1))) acosh(x) = nan if x < -1 If x^2 will overflow, we approximate sqrt(x^2 - 1) == x and compute as log(2*x) = log(2) + log(x). (Note this works because negative x never overflows; x < -1 simply yields nan. This is quite different than asinh!)
| 1144 | // log(2*x) = log(2) + log(x). (Note this works because negative x never |
| 1145 | // overflows; x < -1 simply yields nan. This is quite different than asinh!) |
| 1146 | XlaOp Acosh(XlaOp x) { |
| 1147 | XlaBuilder* b = x.builder(); |
| 1148 | return b->ReportErrorOrReturn([&]() -> StatusOr<XlaOp> { |
| 1149 | TF_ASSIGN_OR_RETURN(auto shape, b->GetShape(x)); |
| 1150 | |
| 1151 | auto one = ScalarLike(x, 1); |
| 1152 | auto neg_one = ScalarLike(x, -1); |
| 1153 | auto nan = FullLike(x, std::numeric_limits<float>::quiet_NaN()); |
| 1154 | |
| 1155 | // return |
| 1156 | // |
| 1157 | // nan if x < -1 |
| 1158 | // log(x) + log(2) if x >= sqrt_max_value |
| 1159 | // log(x + sqrt((x+1)*(x-1))) otherwise |
| 1160 | // |
| 1161 | // TODO(jlebar): For now, we ignore the question of overflow if x is a |
| 1162 | // complex type, because we don't yet have exhaustive tests for complex trig |
| 1163 | // functions. |
| 1164 | auto naive_result = Log(x + Sqrt((x + one) * (x - one))); |
| 1165 | if (primitive_util::IsComplexType(shape.element_type())) { |
| 1166 | return naive_result; |
| 1167 | } |
| 1168 | auto overflow_result = Log(x) + Log(ScalarLike(x, 2)); |
| 1169 | |
| 1170 | auto sqrt_max_value = Sqrt(MaxFiniteValue(b, shape.element_type())); |
| 1171 | return Select(Lt(x, neg_one), nan, |
| 1172 | Select(Ge(x, sqrt_max_value), overflow_result, naive_result)); |
| 1173 | }); |
| 1174 | } |
| 1175 | |
| 1176 | // asinh(x) = log(x + sqrt(x^2 + 1)) |
| 1177 | // |