(FPCore (a b) :precision binary64 (+ a (log (- 1.0 (/ (exp a) (exp b))))))
double code(double a, double b) { return a + log((1.0 - (exp(a) / exp(b)))); }
real(8) function code(a, b) real(8), intent (in) :: a real(8), intent (in) :: b code = a + log((1.0d0 - (exp(a) / exp(b)))) end function
public static double code(double a, double b) { return a + Math.log((1.0 - (Math.exp(a) / Math.exp(b)))); }
def code(a, b): return a + math.log((1.0 - (math.exp(a) / math.exp(b))))
function code(a, b) return Float64(a + log(Float64(1.0 - Float64(exp(a) / exp(b))))) end
function tmp = code(a, b) tmp = a + log((1.0 - (exp(a) / exp(b)))); end
code[a_, b_] := N[(a + N[Log[N[(1.0 - N[(N[Exp[a], $MachinePrecision] / N[Exp[b], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l} \\ a + \log \left(1 - \frac{e^{a}}{e^{b}}\right) \end{array}
Sampling outcomes in binary64 precision:
Herbie found 7 alternatives:
Alternative | Accuracy | Speedup |
---|
(FPCore (a b) :precision binary64 (+ a (log (- 1.0 (/ (exp a) (exp b))))))
double code(double a, double b) { return a + log((1.0 - (exp(a) / exp(b)))); }
real(8) function code(a, b) real(8), intent (in) :: a real(8), intent (in) :: b code = a + log((1.0d0 - (exp(a) / exp(b)))) end function
public static double code(double a, double b) { return a + Math.log((1.0 - (Math.exp(a) / Math.exp(b)))); }
def code(a, b): return a + math.log((1.0 - (math.exp(a) / math.exp(b))))
function code(a, b) return Float64(a + log(Float64(1.0 - Float64(exp(a) / exp(b))))) end
function tmp = code(a, b) tmp = a + log((1.0 - (exp(a) / exp(b)))); end
code[a_, b_] := N[(a + N[Log[N[(1.0 - N[(N[Exp[a], $MachinePrecision] / N[Exp[b], $MachinePrecision]), $MachinePrecision]), $MachinePrecision]], $MachinePrecision]), $MachinePrecision]
\begin{array}{l} \\ a + \log \left(1 - \frac{e^{a}}{e^{b}}\right) \end{array}
(FPCore (a b) :precision binary64 (+ (log (- (expm1 (- a b)))) a))
double code(double a, double b) { return log(-expm1((a - b))) + a; }
public static double code(double a, double b) { return Math.log(-Math.expm1((a - b))) + a; }
def code(a, b): return math.log(-math.expm1((a - b))) + a
function code(a, b) return Float64(log(Float64(-expm1(Float64(a - b)))) + a) end
code[a_, b_] := N[(N[Log[(-N[(Exp[N[(a - b), $MachinePrecision]] - 1), $MachinePrecision])], $MachinePrecision] + a), $MachinePrecision]
\begin{array}{l} \\ \log \left(-\mathsf{expm1}\left(a - b\right)\right) + a \end{array}
Initial program 15.1%
lift--.f64
N/A
sub-neg
N/A
+-commutative
N/A
neg-sub0
N/A
associate-+l-
N/A
lower--.f64
N/A
lift-/.f64
N/A
lift-exp.f64
N/A
lift-exp.f64
N/A
div-exp
N/A
lower-expm1.f64
N/A
lower--.f64
100.0
Applied rewrites100.0%
lift--.f64
N/A
sub0-neg
N/A
lower-neg.f64
100.0
Applied rewrites100.0%
Final simplification100.0%
(FPCore (a b) :precision binary64 (if (<= b 3.8e-18) (+ (log (- (expm1 a))) a) (+ (log1p (- (exp (- b)))) a)))
double code(double a, double b) { double tmp; if (b <= 3.8e-18) { tmp = log(-expm1(a)) + a; } else { tmp = log1p(-exp(-b)) + a; } return tmp; }
public static double code(double a, double b) { double tmp; if (b <= 3.8e-18) { tmp = Math.log(-Math.expm1(a)) + a; } else { tmp = Math.log1p(-Math.exp(-b)) + a; } return tmp; }
def code(a, b): tmp = 0 if b <= 3.8e-18: tmp = math.log(-math.expm1(a)) + a else: tmp = math.log1p(-math.exp(-b)) + a return tmp
function code(a, b) tmp = 0.0 if (b <= 3.8e-18) tmp = Float64(log(Float64(-expm1(a))) + a); else tmp = Float64(log1p(Float64(-exp(Float64(-b)))) + a); end return tmp end
code[a_, b_] := If[LessEqual[b, 3.8e-18], N[(N[Log[(-N[(Exp[a] - 1), $MachinePrecision])], $MachinePrecision] + a), $MachinePrecision], N[(N[Log[1 + (-N[Exp[(-b)], $MachinePrecision])], $MachinePrecision] + a), $MachinePrecision]]
\begin{array}{l} \\ \begin{array}{l} \mathbf{if}\;b \leq 3.8 \cdot 10^{-18}:\\ \;\;\;\;\log \left(-\mathsf{expm1}\left(a\right)\right) + a\\ \mathbf{else}:\\ \;\;\;\;\mathsf{log1p}\left(-e^{-b}\right) + a\\ \end{array} \end{array}
if b < 3.7999999999999998e-18
Initial program 10.9%
lift--.f64
N/A
sub-neg
N/A
+-commutative
N/A
neg-sub0
N/A
associate-+l-
N/A
lower--.f64
N/A
lift-/.f64
N/A
lift-exp.f64
N/A
lift-exp.f64
N/A
div-exp
N/A
lower-expm1.f64
N/A
lower--.f64
100.0
Applied rewrites100.0%
Taylor expanded in b around 0
lower-expm1.f64
57.0
Applied rewrites57.0%
if 3.7999999999999998e-18 < b
Initial program 66.5%
lift-log.f64
N/A
lift--.f64
N/A
sub-neg
N/A
lower-log1p.f64
N/A
lower-neg.f64
66.5
lift-/.f64
N/A
lift-exp.f64
N/A
lift-exp.f64
N/A
div-exp
N/A
lower-exp.f64
N/A
lower--.f64
67.3
Applied rewrites67.3%
Taylor expanded in a around 0
lower-exp.f64
N/A
lower-neg.f64
62.9
Applied rewrites62.9%
Final simplification57.5%
(FPCore (a b) :precision binary64 (+ (log (- (expm1 a))) a))
double code(double a, double b) { return log(-expm1(a)) + a; }
public static double code(double a, double b) { return Math.log(-Math.expm1(a)) + a; }
def code(a, b): return math.log(-math.expm1(a)) + a
function code(a, b) return Float64(log(Float64(-expm1(a))) + a) end
code[a_, b_] := N[(N[Log[(-N[(Exp[a] - 1), $MachinePrecision])], $MachinePrecision] + a), $MachinePrecision]
\begin{array}{l} \\ \log \left(-\mathsf{expm1}\left(a\right)\right) + a \end{array}
Initial program 15.1%
lift--.f64
N/A
sub-neg
N/A
+-commutative
N/A
neg-sub0
N/A
associate-+l-
N/A
lower--.f64
N/A
lift-/.f64
N/A
lift-exp.f64
N/A
lift-exp.f64
N/A
div-exp
N/A
lower-expm1.f64
N/A
lower--.f64
100.0
Applied rewrites100.0%
Taylor expanded in b around 0
lower-expm1.f64
54.2
Applied rewrites54.2%
Final simplification54.2%
(FPCore (a b) :precision binary64 (+ (log1p (- (exp a))) a))
double code(double a, double b) { return log1p(-exp(a)) + a; }
public static double code(double a, double b) { return Math.log1p(-Math.exp(a)) + a; }
def code(a, b): return math.log1p(-math.exp(a)) + a
function code(a, b) return Float64(log1p(Float64(-exp(a))) + a) end
code[a_, b_] := N[(N[Log[1 + (-N[Exp[a], $MachinePrecision])], $MachinePrecision] + a), $MachinePrecision]
\begin{array}{l} \\ \mathsf{log1p}\left(-e^{a}\right) + a \end{array}
Initial program 15.1%
Taylor expanded in b around 0
sub-neg
N/A
lower-log1p.f64
N/A
lower-neg.f64
N/A
lower-exp.f64
11.1
Applied rewrites11.1%
Final simplification11.1%
(FPCore (a b) :precision binary64 (+ (log1p (fma (fma (fma -0.16666666666666666 a -0.5) a -1.0) a -1.0)) a))
double code(double a, double b) { return log1p(fma(fma(fma(-0.16666666666666666, a, -0.5), a, -1.0), a, -1.0)) + a; }
function code(a, b) return Float64(log1p(fma(fma(fma(-0.16666666666666666, a, -0.5), a, -1.0), a, -1.0)) + a) end
code[a_, b_] := N[(N[Log[1 + N[(N[(N[(-0.16666666666666666 * a + -0.5), $MachinePrecision] * a + -1.0), $MachinePrecision] * a + -1.0), $MachinePrecision]], $MachinePrecision] + a), $MachinePrecision]
\begin{array}{l} \\ \mathsf{log1p}\left(\mathsf{fma}\left(\mathsf{fma}\left(\mathsf{fma}\left(-0.16666666666666666, a, -0.5\right), a, -1\right), a, -1\right)\right) + a \end{array}
Initial program 15.1%
Taylor expanded in b around 0
sub-neg
N/A
lower-log1p.f64
N/A
lower-neg.f64
N/A
lower-exp.f64
11.1
Applied rewrites11.1%
Taylor expanded in a around 0
Applied rewrites8.3%
Final simplification8.3%
(FPCore (a b) :precision binary64 (+ (log1p (- -1.0 a)) a))
double code(double a, double b) { return log1p((-1.0 - a)) + a; }
public static double code(double a, double b) { return Math.log1p((-1.0 - a)) + a; }
def code(a, b): return math.log1p((-1.0 - a)) + a
function code(a, b) return Float64(log1p(Float64(-1.0 - a)) + a) end
code[a_, b_] := N[(N[Log[1 + N[(-1.0 - a), $MachinePrecision]], $MachinePrecision] + a), $MachinePrecision]
\begin{array}{l} \\ \mathsf{log1p}\left(-1 - a\right) + a \end{array}
Initial program 15.1%
Taylor expanded in b around 0
sub-neg
N/A
lower-log1p.f64
N/A
lower-neg.f64
N/A
lower-exp.f64
11.1
Applied rewrites11.1%
Taylor expanded in a around 0
Applied rewrites7.9%
Final simplification7.9%
(FPCore (a b) :precision binary64 (+ (log1p -1.0) a))
double code(double a, double b) { return log1p(-1.0) + a; }
public static double code(double a, double b) { return Math.log1p(-1.0) + a; }
def code(a, b): return math.log1p(-1.0) + a
function code(a, b) return Float64(log1p(-1.0) + a) end
code[a_, b_] := N[(N[Log[1 + -1.0], $MachinePrecision] + a), $MachinePrecision]
\begin{array}{l} \\ \mathsf{log1p}\left(-1\right) + a \end{array}
Initial program 15.1%
Taylor expanded in b around 0
sub-neg
N/A
lower-log1p.f64
N/A
lower-neg.f64
N/A
lower-exp.f64
11.1
Applied rewrites11.1%
Taylor expanded in a around 0
Applied rewrites3.1%
Final simplification3.1%
herbie shell --seed 1
(FPCore (a b)
:name "a + log(1 - exp(a)/exp(b))"
:precision binary64
:pre (and (and (<= -2.2e+16 a) (<= a 1.0)) (and (<= -2.2e+16 b) (<= b 1.0)))
(+ a (log (- 1.0 (/ (exp a) (exp b))))))