
(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 5 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) (- (* n (log1p n)) (fma n (log n) 1.0))))
double code(double n) {
return log1p(n) + ((n * log1p(n)) - fma(n, log(n), 1.0));
}
function code(n) return Float64(log1p(n) + Float64(Float64(n * log1p(n)) - fma(n, log(n), 1.0))) end
code[n_] := N[(N[Log[1 + n], $MachinePrecision] + N[(N[(n * N[Log[1 + n], $MachinePrecision]), $MachinePrecision] - N[(n * N[Log[n], $MachinePrecision] + 1.0), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\mathsf{log1p}\left(n\right) + \left(n \cdot \mathsf{log1p}\left(n\right) - \mathsf{fma}\left(n, \log n, 1\right)\right)
\end{array}
Initial program 1.5%
associate--l-N/A
*-commutativeN/A
+-commutativeN/A
distribute-lft-inN/A
*-rgt-identityN/A
associate--l+N/A
+-lowering-+.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
--lowering--.f64N/A
*-lowering-*.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
accelerator-lowering-fma.f64N/A
log-lowering-log.f6498.4
Applied egg-rr98.4%
Final simplification98.4%
(FPCore (n) :precision binary64 (/ 1.0 (/ 1.0 (+ -1.0 (/ 1.0 (/ 1.0 (fma n (log (/ (+ n 1.0) n)) (log1p n))))))))
double code(double n) {
return 1.0 / (1.0 / (-1.0 + (1.0 / (1.0 / fma(n, log(((n + 1.0) / n)), log1p(n))))));
}
function code(n) return Float64(1.0 / Float64(1.0 / Float64(-1.0 + Float64(1.0 / Float64(1.0 / fma(n, log(Float64(Float64(n + 1.0) / n)), log1p(n))))))) end
code[n_] := N[(1.0 / N[(1.0 / N[(-1.0 + N[(1.0 / N[(1.0 / N[(n * N[Log[N[(N[(n + 1.0), $MachinePrecision] / n), $MachinePrecision]], $MachinePrecision] + N[Log[1 + n], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\frac{1}{\frac{1}{-1 + \frac{1}{\frac{1}{\mathsf{fma}\left(n, \log \left(\frac{n + 1}{n}\right), \mathsf{log1p}\left(n\right)\right)}}}}
\end{array}
Initial program 1.5%
associate--l-N/A
*-commutativeN/A
+-commutativeN/A
distribute-lft-inN/A
*-rgt-identityN/A
associate--l+N/A
+-lowering-+.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
--lowering--.f64N/A
*-lowering-*.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
accelerator-lowering-fma.f64N/A
log-lowering-log.f6498.4
Applied egg-rr98.4%
flip-+N/A
div-invN/A
*-lowering-*.f64N/A
Applied egg-rr31.0%
*-commutativeN/A
associate-/r/N/A
/-lowering-/.f64N/A
clear-numN/A
unpow2N/A
unpow2N/A
Applied egg-rr31.0%
flip-+N/A
clear-numN/A
/-lowering-/.f64N/A
clear-numN/A
flip-+N/A
/-lowering-/.f64N/A
accelerator-lowering-fma.f64N/A
Applied egg-rr31.0%
Final simplification31.0%
(FPCore (n) :precision binary64 (+ (log1p n) (fma n (log (/ (+ n 1.0) n)) -1.0)))
double code(double n) {
return log1p(n) + fma(n, log(((n + 1.0) / n)), -1.0);
}
function code(n) return Float64(log1p(n) + fma(n, log(Float64(Float64(n + 1.0) / n)), -1.0)) end
code[n_] := N[(N[Log[1 + n], $MachinePrecision] + N[(n * N[Log[N[(N[(n + 1.0), $MachinePrecision] / n), $MachinePrecision]], $MachinePrecision] + -1.0), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\mathsf{log1p}\left(n\right) + \mathsf{fma}\left(n, \log \left(\frac{n + 1}{n}\right), -1\right)
\end{array}
Initial program 1.5%
associate--l-N/A
*-commutativeN/A
+-commutativeN/A
distribute-lft-inN/A
*-rgt-identityN/A
associate--l+N/A
+-lowering-+.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
--lowering--.f64N/A
*-lowering-*.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
accelerator-lowering-fma.f64N/A
log-lowering-log.f6498.4
Applied egg-rr98.4%
+-commutativeN/A
+-lowering-+.f64N/A
associate--r+N/A
sub-negN/A
*-commutativeN/A
distribute-lft-out--N/A
metadata-evalN/A
accelerator-lowering-fma.f64N/A
+-commutativeN/A
metadata-evalN/A
sub-negN/A
diff-logN/A
log-lowering-log.f64N/A
/-lowering-/.f64N/A
sub-negN/A
metadata-evalN/A
+-commutativeN/A
+-lowering-+.f64N/A
Applied egg-rr31.0%
Final simplification31.0%
(FPCore (n) :precision binary64 (+ -1.0 (fma (- (log n)) n (* (log1p n) (+ n 1.0)))))
double code(double n) {
return -1.0 + fma(-log(n), n, (log1p(n) * (n + 1.0)));
}
function code(n) return Float64(-1.0 + fma(Float64(-log(n)), n, Float64(log1p(n) * Float64(n + 1.0)))) end
code[n_] := N[(-1.0 + N[((-N[Log[n], $MachinePrecision]) * n + N[(N[Log[1 + n], $MachinePrecision] * N[(n + 1.0), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
-1 + \mathsf{fma}\left(-\log n, n, \mathsf{log1p}\left(n\right) \cdot \left(n + 1\right)\right)
\end{array}
Initial program 1.5%
sub-negN/A
+-commutativeN/A
*-commutativeN/A
distribute-lft-neg-inN/A
accelerator-lowering-fma.f64N/A
neg-lowering-neg.f64N/A
log-lowering-log.f64N/A
*-lowering-*.f64N/A
+-lowering-+.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f643.2
Applied egg-rr3.2%
Final simplification3.2%
(FPCore (n) :precision binary64 (fma (- (log n)) n (fma (+ n 1.0) (log1p n) -1.0)))
double code(double n) {
return fma(-log(n), n, fma((n + 1.0), log1p(n), -1.0));
}
function code(n) return fma(Float64(-log(n)), n, fma(Float64(n + 1.0), log1p(n), -1.0)) end
code[n_] := N[((-N[Log[n], $MachinePrecision]) * n + N[(N[(n + 1.0), $MachinePrecision] * N[Log[1 + n], $MachinePrecision] + -1.0), $MachinePrecision]), $MachinePrecision]
\begin{array}{l}
\\
\mathsf{fma}\left(-\log n, n, \mathsf{fma}\left(n + 1, \mathsf{log1p}\left(n\right), -1\right)\right)
\end{array}
Initial program 1.5%
sub-negN/A
sub-negN/A
+-commutativeN/A
associate-+l+N/A
*-commutativeN/A
distribute-lft-neg-inN/A
accelerator-lowering-fma.f64N/A
neg-lowering-neg.f64N/A
log-lowering-log.f64N/A
accelerator-lowering-fma.f64N/A
+-lowering-+.f64N/A
+-commutativeN/A
accelerator-lowering-log1p.f64N/A
metadata-eval3.2
Applied egg-rr3.2%
(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 2024207
(FPCore (n)
:name "logs (example 3.8)"
:precision binary64
:pre (> n 6.8e+15)
:alt
(! :herbie-platform default (- (log (+ n 1)) (- (/ 1 (* 2 n)) (- (/ 1 (* 3 (* n n))) (/ 4 (pow n 3))))))
(- (- (* (+ n 1.0) (log (+ n 1.0))) (* n (log n))) 1.0))