views:

119

answers:

1

Multiplying two numbers in log space means adding them:

log_multiply(x, y) = log( exp(x) * exp(y) )
                   = x + y

Adding two numbers in log space means you do a special log-add operation:

log_add(x, y) = log( exp(x) + exp(y) )

which is implemented in the following code, in a way that doesn't require us to take the two exponentials (and lose runtime speed and precision):

  double log_add(double x, double y) {
    if(x == neginf)
      return y;
    if(y == neginf)
      return x;
    return max(x, y) + log1p(exp( -fabs(x - y) ));
  }

(Here is another one.)

But here is the question:

Is there a trick to do it for subtraction as well?

log_subtract(x, y) = log( exp(x) - exp(y) )

without having to take the exponents and lose precision?

  double log_subtract(double x, double y) {
    // ?
  }
+3  A: 

How about

double log_subtract(double x, double y) {
  if(x <= y)
    // error!! computing the log of a negative number
  if(y == neginf)
    return x;
  return x + log1p(-exp(y-x));
}

That's just based on some quick math I did...

David Zaslavsky
I had just come to the same thing. Thought for sure I was going to get my first upvote, but you beat me.
FarmBoy
Cool. Should be if(x<y) in the 2nd line, I guess.
I used <= because if x == y, you'd wind up taking the logarithm of 0, which is undefined.
David Zaslavsky
logarithm of 0 is fine: log(0)=-inf, exp(-inf)=0
Well... if it's convenient to do it that way in your program, go right ahead, but mathematically that's not true. The *limit* of log(x) as x goes to 0 (for positive x) is indeed -inf, but log(0) itself has no value.
David Zaslavsky
Well ... mathematically, the limit of log(x), x->+0 does not exist.
Yeah, I just often use some form of infinity to denote nonexistent limits. (I'm a physicist, for my purposes they're pretty much the same thing ;-)
David Zaslavsky