
(FPCore (x) :precision binary64 (/ (log (- 1.0 x)) (log (+ 1.0 x))))
double code(double x) {
return log((1.0 - x)) / log((1.0 + x));
}
real(8) function code(x)
real(8), intent (in) :: x
code = log((1.0d0 - x)) / log((1.0d0 + x))
end function
public static double code(double x) {
return Math.log((1.0 - x)) / Math.log((1.0 + x));
}
def code(x): return math.log((1.0 - x)) / math.log((1.0 + x))
function code(x) return Float64(log(Float64(1.0 - x)) / log(Float64(1.0 + x))) end
function tmp = code(x) tmp = log((1.0 - x)) / log((1.0 + x)); end
code[x_] := N[(N[Log[N[(1.0 - x), $MachinePrecision]], $MachinePrecision] / N[Log[N[(1.0 + x), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\frac{\log \left(1 - x\right)}{\log \left(1 + x\right)}
\end{array}
Sampling outcomes in binary64 precision:
Herbie found 9 alternatives:
| Alternative | Accuracy | Speedup |
|---|
(FPCore (x) :precision binary64 (/ (log (- 1.0 x)) (log (+ 1.0 x))))
double code(double x) {
return log((1.0 - x)) / log((1.0 + x));
}
real(8) function code(x)
real(8), intent (in) :: x
code = log((1.0d0 - x)) / log((1.0d0 + x))
end function
public static double code(double x) {
return Math.log((1.0 - x)) / Math.log((1.0 + x));
}
def code(x): return math.log((1.0 - x)) / math.log((1.0 + x))
function code(x) return Float64(log(Float64(1.0 - x)) / log(Float64(1.0 + x))) end
function tmp = code(x) tmp = log((1.0 - x)) / log((1.0 + x)); end
code[x_] := N[(N[Log[N[(1.0 - x), $MachinePrecision]], $MachinePrecision] / N[Log[N[(1.0 + x), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\frac{\log \left(1 - x\right)}{\log \left(1 + x\right)}
\end{array}
(FPCore (x)
:precision binary64
(let* ((t_0 (fma x (* x -0.4166666666666667) -1.0))
(t_1 (fma x (fma x -0.4166666666666667 -0.5) -1.0)))
(fma
x
(/
(fma (* x x) 0.5833333333333334 1.0)
(- (/ (* t_0 t_0) t_1) (/ (* x (* x 0.25)) t_1)))
-1.0)))
double code(double x) {
double t_0 = fma(x, (x * -0.4166666666666667), -1.0);
double t_1 = fma(x, fma(x, -0.4166666666666667, -0.5), -1.0);
return fma(x, (fma((x * x), 0.5833333333333334, 1.0) / (((t_0 * t_0) / t_1) - ((x * (x * 0.25)) / t_1))), -1.0);
}
function code(x) t_0 = fma(x, Float64(x * -0.4166666666666667), -1.0) t_1 = fma(x, fma(x, -0.4166666666666667, -0.5), -1.0) return fma(x, Float64(fma(Float64(x * x), 0.5833333333333334, 1.0) / Float64(Float64(Float64(t_0 * t_0) / t_1) - Float64(Float64(x * Float64(x * 0.25)) / t_1))), -1.0) end
code[x_] := Block[{t$95$0 = N[(x * N[(x * -0.4166666666666667), $MachinePrecision] + -1.0), $MachinePrecision]}, Block[{t$95$1 = N[(x * N[(x * -0.4166666666666667 + -0.5), $MachinePrecision] + -1.0), $MachinePrecision]}, N[(x * N[(N[(N[(x * x), $MachinePrecision] * 0.5833333333333334 + 1.0), $MachinePrecision] / N[(N[(N[(t$95$0 * t$95$0), $MachinePrecision] / t$95$1), $MachinePrecision] - N[(N[(x * N[(x * 0.25), $MachinePrecision]), $MachinePrecision] / t$95$1), $MachinePrecision]), $MachinePrecision]), $MachinePrecision] + -1.0), $MachinePrecision]]]
\begin{array}{l}
\\
\begin{array}{l}
t_0 := \mathsf{fma}\left(x, x \cdot -0.4166666666666667, -1\right)\\
t_1 := \mathsf{fma}\left(x, \mathsf{fma}\left(x, -0.4166666666666667, -0.5\right), -1\right)\\
\mathsf{fma}\left(x, \frac{\mathsf{fma}\left(x \cdot x, 0.5833333333333334, 1\right)}{\frac{t\_0 \cdot t\_0}{t\_1} - \frac{x \cdot \left(x \cdot 0.25\right)}{t\_1}}, -1\right)
\end{array}
\end{array}
Initial program 2.8%
Taylor expanded in x around 0
sub-negN/A
metadata-evalN/A
lower-fma.f64N/A
sub-negN/A
metadata-evalN/A
lower-fma.f64N/A
sub-negN/A
*-commutativeN/A
metadata-evalN/A
lower-fma.f6499.7
Applied rewrites99.7%
Applied rewrites99.7%
Taylor expanded in x around 0
Applied rewrites99.7%
Applied rewrites99.7%
(FPCore (x)
:precision binary64
(let* ((t_0 (* x (fma x -0.4166666666666667 0.5))))
(fma
x
(/
(fma (* x x) 0.5833333333333334 1.0)
(/ (- 1.0 (* t_0 t_0)) (- -1.0 t_0)))
-1.0)))
double code(double x) {
double t_0 = x * fma(x, -0.4166666666666667, 0.5);
return fma(x, (fma((x * x), 0.5833333333333334, 1.0) / ((1.0 - (t_0 * t_0)) / (-1.0 - t_0))), -1.0);
}
function code(x) t_0 = Float64(x * fma(x, -0.4166666666666667, 0.5)) return fma(x, Float64(fma(Float64(x * x), 0.5833333333333334, 1.0) / Float64(Float64(1.0 - Float64(t_0 * t_0)) / Float64(-1.0 - t_0))), -1.0) end
code[x_] := Block[{t$95$0 = N[(x * N[(x * -0.4166666666666667 + 0.5), $MachinePrecision]), $MachinePrecision]}, N[(x * N[(N[(N[(x * x), $MachinePrecision] * 0.5833333333333334 + 1.0), $MachinePrecision] / N[(N[(1.0 - N[(t$95$0 * t$95$0), $MachinePrecision]), $MachinePrecision] / N[(-1.0 - t$95$0), $MachinePrecision]), $MachinePrecision]), $MachinePrecision] + -1.0), $MachinePrecision]]
\begin{array}{l}
\\
\begin{array}{l}
t_0 := x \cdot \mathsf{fma}\left(x, -0.4166666666666667, 0.5\right)\\
\mathsf{fma}\left(x, \frac{\mathsf{fma}\left(x \cdot x, 0.5833333333333334, 1\right)}{\frac{1 - t\_0 \cdot t\_0}{-1 - t\_0}}, -1\right)
\end{array}
\end{array}
Initial program 4.1%
Taylor expanded in x around 0
sub-negN/A
metadata-evalN/A
lower-fma.f64N/A
sub-negN/A
metadata-evalN/A
lower-fma.f64N/A
sub-negN/A
*-commutativeN/A
metadata-evalN/A
lower-fma.f6499.5
Applied rewrites99.5%
Applied rewrites99.5%
Taylor expanded in x around 0
Applied rewrites99.5%
Applied rewrites99.5%
(FPCore (x) :precision binary64 (/ (log1p (- x)) (log1p x)))
double code(double x) {
return log1p(-x) / log1p(x);
}
public static double code(double x) {
return Math.log1p(-x) / Math.log1p(x);
}
def code(x): return math.log1p(-x) / math.log1p(x)
function code(x) return Float64(log1p(Float64(-x)) / log1p(x)) end
code[x_] := N[(N[Log[1 + (-x)], $MachinePrecision] / N[Log[1 + x], $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\frac{\mathsf{log1p}\left(-x\right)}{\mathsf{log1p}\left(x\right)}
\end{array}
herbie shell --seed 2024229
(FPCore (x)
:name "qlog (example 3.10)"
:precision binary64
:pre (<= (fabs x) 1.0)
:alt
(! :herbie-platform default (/ (log1p (- x)) (log1p x)))
(/ (log (- 1.0 x)) (log (+ 1.0 x))))