
(FPCore (n) :precision binary64 (- (- (* (+ n 1.0) (log (+ n 1.0))) (* n (log n))) 1.0))
double code(double n) {
return (((n + 1.0) * log((n + 1.0))) - (n * log(n))) - 1.0;
}
real(8) function code(n)
real(8), intent (in) :: n
code = (((n + 1.0d0) * log((n + 1.0d0))) - (n * log(n))) - 1.0d0
end function
public static double code(double n) {
return (((n + 1.0) * Math.log((n + 1.0))) - (n * Math.log(n))) - 1.0;
}
def code(n): return (((n + 1.0) * math.log((n + 1.0))) - (n * math.log(n))) - 1.0
function code(n) return Float64(Float64(Float64(Float64(n + 1.0) * log(Float64(n + 1.0))) - Float64(n * log(n))) - 1.0) end
function tmp = code(n) tmp = (((n + 1.0) * log((n + 1.0))) - (n * log(n))) - 1.0; end
code[n_] := N[(N[(N[(N[(n + 1.0), $MachinePrecision] * N[Log[N[(n + 1.0), $MachinePrecision]], $MachinePrecision]), $MachinePrecision] - N[(n * N[Log[n], $MachinePrecision]), $MachinePrecision]), $MachinePrecision] - 1.0), $MachinePrecision]
\begin{array}{l}
\\
\left(\left(n + 1\right) \cdot \log \left(n + 1\right) - n \cdot \log n\right) - 1
\end{array}
Sampling outcomes in binary64 precision:
Herbie found 2 alternatives:
| Alternative | Accuracy | Speedup |
|---|
(FPCore (n) :precision binary64 (- (- (* (+ n 1.0) (log (+ n 1.0))) (* n (log n))) 1.0))
double code(double n) {
return (((n + 1.0) * log((n + 1.0))) - (n * log(n))) - 1.0;
}
real(8) function code(n)
real(8), intent (in) :: n
code = (((n + 1.0d0) * log((n + 1.0d0))) - (n * log(n))) - 1.0d0
end function
public static double code(double n) {
return (((n + 1.0) * Math.log((n + 1.0))) - (n * Math.log(n))) - 1.0;
}
def code(n): return (((n + 1.0) * math.log((n + 1.0))) - (n * math.log(n))) - 1.0
function code(n) return Float64(Float64(Float64(Float64(n + 1.0) * log(Float64(n + 1.0))) - Float64(n * log(n))) - 1.0) end
function tmp = code(n) tmp = (((n + 1.0) * log((n + 1.0))) - (n * log(n))) - 1.0; end
code[n_] := N[(N[(N[(N[(n + 1.0), $MachinePrecision] * N[Log[N[(n + 1.0), $MachinePrecision]], $MachinePrecision]), $MachinePrecision] - N[(n * N[Log[n], $MachinePrecision]), $MachinePrecision]), $MachinePrecision] - 1.0), $MachinePrecision]
\begin{array}{l}
\\
\left(\left(n + 1\right) \cdot \log \left(n + 1\right) - n \cdot \log n\right) - 1
\end{array}
(FPCore (n) :precision binary64 (+ (log1p n) (fma n (- (log1p n) (log n)) -1.0)))
double code(double n) {
return log1p(n) + fma(n, (log1p(n) - log(n)), -1.0);
}
function code(n) return Float64(log1p(n) + fma(n, Float64(log1p(n) - log(n)), -1.0)) end
code[n_] := N[(N[Log[1 + n], $MachinePrecision] + N[(n * N[(N[Log[1 + n], $MachinePrecision] - N[Log[n], $MachinePrecision]), $MachinePrecision] + -1.0), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\mathsf{log1p}\left(n\right) + \mathsf{fma}\left(n, \mathsf{log1p}\left(n\right) - \log n, -1\right)
\end{array}
Initial program 1.5%
distribute-rgt1-in1.5%
associate--l+30.5%
associate--l+30.5%
+-commutative30.5%
log1p-def30.5%
distribute-lft-out--31.1%
fma-neg31.1%
+-commutative31.1%
log1p-def31.1%
metadata-eval31.1%
Simplified31.1%
Final simplification31.1%
(FPCore (n) :precision binary64 (+ (* (+ n 1.0) (log (+ n 1.0))) (- -1.0 (* n (log n)))))
double code(double n) {
return ((n + 1.0) * log((n + 1.0))) + (-1.0 - (n * log(n)));
}
real(8) function code(n)
real(8), intent (in) :: n
code = ((n + 1.0d0) * log((n + 1.0d0))) + ((-1.0d0) - (n * log(n)))
end function
public static double code(double n) {
return ((n + 1.0) * Math.log((n + 1.0))) + (-1.0 - (n * Math.log(n)));
}
def code(n): return ((n + 1.0) * math.log((n + 1.0))) + (-1.0 - (n * math.log(n)))
function code(n) return Float64(Float64(Float64(n + 1.0) * log(Float64(n + 1.0))) + Float64(-1.0 - Float64(n * log(n)))) end
function tmp = code(n) tmp = ((n + 1.0) * log((n + 1.0))) + (-1.0 - (n * log(n))); end
code[n_] := N[(N[(N[(n + 1.0), $MachinePrecision] * N[Log[N[(n + 1.0), $MachinePrecision]], $MachinePrecision]), $MachinePrecision] + N[(-1.0 - N[(n * N[Log[n], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\left(n + 1\right) \cdot \log \left(n + 1\right) + \left(-1 - n \cdot \log n\right)
\end{array}
Initial program 1.5%
associate--l-3.1%
Simplified3.1%
Final simplification3.1%
(FPCore (n) :precision binary64 (- (log (+ n 1.0)) (- (/ 1.0 (* 2.0 n)) (- (/ 1.0 (* 3.0 (* n n))) (/ 4.0 (pow n 3.0))))))
double code(double n) {
return log((n + 1.0)) - ((1.0 / (2.0 * n)) - ((1.0 / (3.0 * (n * n))) - (4.0 / pow(n, 3.0))));
}
real(8) function code(n)
real(8), intent (in) :: n
code = log((n + 1.0d0)) - ((1.0d0 / (2.0d0 * n)) - ((1.0d0 / (3.0d0 * (n * n))) - (4.0d0 / (n ** 3.0d0))))
end function
public static double code(double n) {
return Math.log((n + 1.0)) - ((1.0 / (2.0 * n)) - ((1.0 / (3.0 * (n * n))) - (4.0 / Math.pow(n, 3.0))));
}
def code(n): return math.log((n + 1.0)) - ((1.0 / (2.0 * n)) - ((1.0 / (3.0 * (n * n))) - (4.0 / math.pow(n, 3.0))))
function code(n) return Float64(log(Float64(n + 1.0)) - Float64(Float64(1.0 / Float64(2.0 * n)) - Float64(Float64(1.0 / Float64(3.0 * Float64(n * n))) - Float64(4.0 / (n ^ 3.0))))) end
function tmp = code(n) tmp = log((n + 1.0)) - ((1.0 / (2.0 * n)) - ((1.0 / (3.0 * (n * n))) - (4.0 / (n ^ 3.0)))); end
code[n_] := N[(N[Log[N[(n + 1.0), $MachinePrecision]], $MachinePrecision] - N[(N[(1.0 / N[(2.0 * n), $MachinePrecision]), $MachinePrecision] - N[(N[(1.0 / N[(3.0 * N[(n * n), $MachinePrecision]), $MachinePrecision]), $MachinePrecision] - N[(4.0 / N[Power[n, 3.0], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\log \left(n + 1\right) - \left(\frac{1}{2 \cdot n} - \left(\frac{1}{3 \cdot \left(n \cdot n\right)} - \frac{4}{{n}^{3}}\right)\right)
\end{array}
herbie shell --seed 2024039
(FPCore (n)
:name "logs (example 3.8)"
:precision binary64
:pre (> n 6.8e+15)
:herbie-target
(- (log (+ n 1.0)) (- (/ 1.0 (* 2.0 n)) (- (/ 1.0 (* 3.0 (* n n))) (/ 4.0 (pow n 3.0)))))
(- (- (* (+ n 1.0) (log (+ n 1.0))) (* n (log n))) 1.0))