Average Error: 38.7 → 0.3
Time: 30.9s
Precision: 64
\[\log \left(1.0 + x\right)\]
\[\begin{array}{l} \mathbf{if}\;x \le 4.018374793923451 \cdot 10^{-06}:\\ \;\;\;\;\mathsf{fma}\left(\frac{x}{1.0} \cdot \frac{x}{1.0}, \frac{-1}{2}, \mathsf{fma}\left(1.0, x, \log 1.0\right)\right)\\ \mathbf{else}:\\ \;\;\;\;\log \left(1.0 + x\right)\\ \end{array}\]
\log \left(1.0 + x\right)
\begin{array}{l}
\mathbf{if}\;x \le 4.018374793923451 \cdot 10^{-06}:\\
\;\;\;\;\mathsf{fma}\left(\frac{x}{1.0} \cdot \frac{x}{1.0}, \frac{-1}{2}, \mathsf{fma}\left(1.0, x, \log 1.0\right)\right)\\

\mathbf{else}:\\
\;\;\;\;\log \left(1.0 + x\right)\\

\end{array}
double f(double x) {
        double r3328260 = 1.0;
        double r3328261 = x;
        double r3328262 = r3328260 + r3328261;
        double r3328263 = log(r3328262);
        return r3328263;
}

double f(double x) {
        double r3328264 = x;
        double r3328265 = 4.018374793923451e-06;
        bool r3328266 = r3328264 <= r3328265;
        double r3328267 = 1.0;
        double r3328268 = r3328264 / r3328267;
        double r3328269 = r3328268 * r3328268;
        double r3328270 = -0.5;
        double r3328271 = log(r3328267);
        double r3328272 = fma(r3328267, r3328264, r3328271);
        double r3328273 = fma(r3328269, r3328270, r3328272);
        double r3328274 = r3328267 + r3328264;
        double r3328275 = log(r3328274);
        double r3328276 = r3328266 ? r3328273 : r3328275;
        return r3328276;
}

Error

Bits error versus x

Target

Original38.7
Target0.2
Herbie0.3
\[\begin{array}{l} \mathbf{if}\;1.0 + x = 1.0:\\ \;\;\;\;x\\ \mathbf{else}:\\ \;\;\;\;\frac{x \cdot \log \left(1.0 + x\right)}{\left(1.0 + x\right) - 1.0}\\ \end{array}\]

Derivation

  1. Split input into 2 regimes
  2. if x < 4.018374793923451e-06

    1. Initial program 58.9

      \[\log \left(1.0 + x\right)\]
    2. Taylor expanded around 0 0.4

      \[\leadsto \color{blue}{\left(\log 1.0 + 1.0 \cdot x\right) - \frac{1}{2} \cdot \frac{{x}^{2}}{{1.0}^{2}}}\]
    3. Simplified0.4

      \[\leadsto \color{blue}{\mathsf{fma}\left(\frac{x}{1.0} \cdot \frac{x}{1.0}, \frac{-1}{2}, \mathsf{fma}\left(1.0, x, \log 1.0\right)\right)}\]

    if 4.018374793923451e-06 < x

    1. Initial program 0.1

      \[\log \left(1.0 + x\right)\]
    2. Using strategy rm
    3. Applied add-log-exp0.1

      \[\leadsto \color{blue}{\log \left(e^{\log \left(1.0 + x\right)}\right)}\]
    4. Simplified0.1

      \[\leadsto \log \color{blue}{\left(x + 1.0\right)}\]
  3. Recombined 2 regimes into one program.
  4. Final simplification0.3

    \[\leadsto \begin{array}{l} \mathbf{if}\;x \le 4.018374793923451 \cdot 10^{-06}:\\ \;\;\;\;\mathsf{fma}\left(\frac{x}{1.0} \cdot \frac{x}{1.0}, \frac{-1}{2}, \mathsf{fma}\left(1.0, x, \log 1.0\right)\right)\\ \mathbf{else}:\\ \;\;\;\;\log \left(1.0 + x\right)\\ \end{array}\]

Reproduce

herbie shell --seed 2019165 +o rules:numerics
(FPCore (x)
  :name "ln(1 + x)"

  :herbie-target
  (if (== (+ 1.0 x) 1.0) x (/ (* x (log (+ 1.0 x))) (- (+ 1.0 x) 1.0)))

  (log (+ 1.0 x)))