| 212 | // log(m) via a polynomial in (m-1) on [0, 1]. |
| 213 | template <typename F> |
| 214 | inline F log_natural_(F value) FL_NOEXCEPT { |
| 215 | if (value <= F(0)) return F(-1e30); // -inf surrogate |
| 216 | int e = 0; |
| 217 | while (value >= F(2)) { value *= F(0.5); ++e; } |
| 218 | while (value < F(1)) { value *= F(2); --e; } |
| 219 | // value ∈ [1, 2); evaluate log(value) via Taylor around 1: let u = value - 1. |
| 220 | // log(1+u) = u - u²/2 + u³/3 - u⁴/4 + ... |
| 221 | // Use enough terms for ~5-decimal accuracy on [0, 1]. |
| 222 | const F u = value - F(1); |
| 223 | const F u2 = u * u; |
| 224 | const F u3 = u2 * u; |
| 225 | const F u4 = u2 * u2; |
| 226 | const F u5 = u4 * u; |
| 227 | const F u6 = u4 * u2; |
| 228 | const F u7 = u6 * u; |
| 229 | F log_m = u - u2 * F(0.5) + u3 * F(1.0 / 3.0) - u4 * F(0.25) |
| 230 | + u5 * F(0.2) - u6 * F(1.0 / 6.0) + u7 * F(1.0 / 7.0); |
| 231 | const F kLn2 = F(0.69314718055994530942); |
| 232 | return log_m + F(e) * kLn2; |
| 233 | } |
| 234 | |
| 235 | } // namespace detail |
| 236 | |