From: <donsourceforgexxz@is...>  20090117 03:05:38

Gabriel Dos Reis writes: > The call to the function log in the form > (log (expt 234 108) 10) > signals a floating point overflow. > I'm not sure the hyperspec specifies an exceptional > situation in this case. Both SBCL and GCL evaluates > the form without fuss. Just as a guess, the integer (expt ...) is probably being converted to float, and this integer is too big to be converted. Perhaps the code should check the size and use a larger float format if necessary. I was wondering what type of result should be expected here. The hyperspec says log can return either an integer or float in cases where the result is actually an integer, but it doesn't say anything about which type of float should be returned in any given case. I guess for an integer it would make sense to try to return a number of significant digits similar to the number of digits in the integer, or as many as possible for really big integers. Maybe the sum of the numbers of digits for the integers in rationals? In this case the (expt ...) fits in a double float, but I still think it should be converted to a long float, and then the log will also end up being a long float. 
From: Gabriel Dos Reis <gdr@in...>  20090117 03:15:34

On Fri, Jan 16, 2009 at 9:05 PM, Don Cohen <donsourceforgexxz@...> wrote: > Gabriel Dos Reis writes: > > The call to the function log in the form > > (log (expt 234 108) 10) > > signals a floating point overflow. > > I'm not sure the hyperspec specifies an exceptional > > situation in this case. Both SBCL and GCL evaluates > > the form without fuss. > Just as a guess, the integer (expt ...) is probably being converted to > float, and this integer is too big to be converted. > Perhaps the code should check the size and use a larger float format > if necessary. I was wondering what type of result should be expected > here. I think a result as floating point number is OK  that is what the other two Lisps do. But, a floating overflow signal is just not good... > The hyperspec says log can return either an integer or float in > cases where the result is actually an integer, but it doesn't say > anything about which type of float should be returned in any given > case. I guess for an integer it would make sense to try to return a > number of significant digits similar to the number of digits in the > integer, or as many as possible for really big integers. > Maybe the sum of the numbers of digits for the integers in rationals? > In this case the (expt ...) fits in a double float, but I still think > it should be converted to a long float, and then the log will also end > up being a long float. > hmm.  Gaby 
From: <donsourceforgexxz@is...>  20090117 03:59:05

Gabriel Dos Reis writes: > > Just as a guess, the integer (expt ...) is probably being converted to > > float, and this integer is too big to be converted. > I think a result as floating point number is OK  that is what the > other two Lisps do. But, a floating overflow signal is just not good... Break 1 [3]> (coerce (expt 234 108) 'DOUBLEFLOAT) 7.5043416907592645d255 Break 1 [3]> (log * 10) 255.87531260029542d0 Break 1 [3]> (coerce (expt 234 108) 'FLOAT) ***  COERCE: floating point overflow 
From: Kaz Kylheku <kkylheku@gm...>  20090117 08:30:13

On Fri, Jan 16, 2009 at 7:05 PM, Don Cohen <donsourceforgexxz@...> wrote: > Gabriel Dos Reis writes: > > The call to the function log in the form > > (log (expt 234 108) 10) > > signals a floating point overflow. > > I'm not sure the hyperspec specifies an exceptional > > situation in this case. Both SBCL and GCL evaluates > > the form without fuss. > Just as a guess, the integer (expt ...) is probably being converted to > float, and this integer is too big to be converted. Uh, you're using exponentiation to create a large number, which you then reduce with a logarithm. Algebra calling! Purely mathematically speaking (not numerically): (log (expt base1 exponent) base2) ==> (* exponent (log base1 base2)) So: (* 108 (log 234 10)) > 255.87532 > Perhaps the code should check the size and use a larger float format > if necessary. I was wondering what type of result should be expected > here. Given that the mathematical value is an irrational number close to 255.87532, I'd say that all bets are off for an integer or rational. :) By the way, you can check that the result 255 is in the right ball park by calculating the string length of the decimarl representation of the big number (since the base for your reducing log is 10). (length (princtostring (expt 234 108))) > 256 > The hyperspec says log can return either an integer or float in > cases where the result is actually an integer. CLISP's log is quite nicely behaved like that. It returns rationals too: (log 10 100) > 1/2. 
From: Kaz Kylheku <kkylheku@gm...>  20090117 08:35:40

On Fri, Jan 16, 2009 at 7:05 PM, Don Cohen <donsourceforgexxz@...> wrote: > Gabriel Dos Reis writes: > > The call to the function log in the form > > (log (expt 234 108) 10) > > signals a floating point overflow. > > I'm not sure the hyperspec specifies an exceptional > > situation in this case. Both SBCL and GCL evaluates > > the form without fuss. > Just as a guess, the integer (expt ...) is probably being converted to > float, and this integer is too big to be converted. Uh, you're using exponentiation to create a large number, which you then reduce with a logarithm. Algebra calling! Purely mathematically speaking (not numerically): (log (expt base1 exponent) base2) ==> (* exponent (log base1 base2)) So: (* 108 (log 234 10)) > 255.87532 > Perhaps the code should check the size and use a larger float format > if necessary. I was wondering what type of result should be expected > here. Given that the mathematical value is an irrational number close to 255.87532, I'd say that all bets are off for an integer or rational. :) By the way, you can check that the result 255 is in the right ball park by calculating the string length of the decimarl representation of the big number (since the base for your reducing log is 10). (length (princtostring (expt 234 108))) > 256 > The hyperspec says log can return either an integer or float in > cases where the result is actually an integer. CLISP's log is quite nicely behaved like that. It returns rationals too: (log 10 100) > 1/2. 
From: Gabriel Dos Reis <gdr@in...>  20090117 09:21:22

On Sat, Jan 17, 2009 at 2:30 AM, Kaz Kylheku <kkylheku@...> wrote: > On Fri, Jan 16, 2009 at 7:05 PM, Don Cohen > <donsourceforgexxz@...> wrote: >> Gabriel Dos Reis writes: >> > The call to the function log in the form >> > (log (expt 234 108) 10) >> > signals a floating point overflow. >> > I'm not sure the hyperspec specifies an exceptional >> > situation in this case. Both SBCL and GCL evaluates >> > the form without fuss. >> Just as a guess, the integer (expt ...) is probably being converted to >> float, and this integer is too big to be converted. > > Uh, you're using exponentiation to create a large number, which you > then reduce with a logarithm. Algebra calling! Obviously the testcase was reduced from more complicated realworld situations, and I hope the real issue is not summarily dismissed on the ground of 'Algebra calling!'. The testcase was distilled from the Computer Algebra System OpenAxiom, see http://www.openaxiom.org/ The value of (expt 234 108) was created as a result of long and complicated computations. The log part happens only long after the computation when attempting to display the result of the computation.  Gaby 
From: Kaz Kylheku <kkylheku@gm...>  20090117 10:02:23

On Sat, Jan 17, 2009 at 1:21 AM, Gabriel Dos Reis <gdr@...> wrote: > On Sat, Jan 17, 2009 at 2:30 AM, Kaz Kylheku <kkylheku@...> wrote: >> Uh, you're using exponentiation to create a large number, which you >> then reduce with a logarithm. Algebra calling! > > Obviously the testcase was reduced from more complicated > realworld situations, and I hope the real issue is not > summarily dismissed on the ground of 'Algebra calling!'. > The testcase was distilled from the Computer Algebra System > OpenAxiom, see > > http://www.openaxiom.org/ And what does it have to say about this? ;) > The value of (expt 234 108) was created as a result of long > and complicated computations. We have not exhausted the properties of logarithms yet. There is also this: log (x/y) = log x  log y log x = log (x/y) + log y We can transform a logarithm of large bignum x into a logarithm of a fraction of two bignums (which it itself not a large number just a number with a large precision). CLISP's log can handle such an animal better. Let's cheat a little in choosing a y; we already know that the answer is 255 plus a fractional part. So let's choose y so that log y is 255. In other words, let y be (EXPT 10 255). What do we have to add to 255 to get the answer? (log (/ (expt 234 108) (expt 10 255)) 10) > 0.87531257 ;; See, CLISP does it. The 255 we can get by taking (exp 234 108) as a string, and using the length. But typographic hacks are ugly; it is more elegant to search numerically for a suitable y. Basically it can be a value that is near x. Say, one that is smaller than x, but not smaller than 1/10 x. But other values in nearby orders of magnitude, maybe even quite distant ones, should work. Our criteria are that y must be a power of 10, so the log will be an integer, and will work for this large number. And (log (/ x y) 10) must work, of course. An efficient search (in the logarithm space) should be possible to find a power of 10 y that is close in magnitude to the input quantity x. Suppose that the initial guess is 1000. If that's too small, you can double the number of digits by squaring it to 1000000. Then square again if that's too small. It will quickly grow. If it grows past x, then apply a binary search (translated to work arithmetically over powers of 10). Hope this is useful in some way. 
From: Kaz Kylheku <kkylheku@gm...>  20090117 11:09:28

Here is a crazy function I hacked up (defun bignumlog (x &optional (b 10)) "logarithm function for CLISP that tries to handle large numbers when the answer is real, and the LOG function blows up. This uses the transformation log x = log x / y + log y. A suitable y is found which is a power of the base that is close to magnitude to x. CLISP can deal with logs of small rations between large bignums better than logs of bignum integers." ;; cases we don't handle (when (or (minusp x) (minusp b) (not (integerp x)) (not (integerp b))) (log x b)) ;; Try LOG function first, but don't bother ;; if X is ``obviously'' too large by inspection. (let* ((obviouslytoolarge (loadtimevalue (expt 10 50))) (trylog (if (not (> x obviouslytoolarge)) (ignoreerrors (log x b))))) (if trylog trylog (loop with y = (expt b 100) with lowestacceptable = (/ x (expt b 4)) with lowprobe = 0 with highprobe = nil do (flet ((bisect() (let* ((delta (/ highprobe lowprobe)) (digits (log delta b))) (* lowprobe (expt b (truncate digits 2)))))) (cond ((< y lowestacceptable) (when (> y lowprobe) (setf lowprobe y)) (if highprobe (setf y (bisect)) (setf y (* y y)))) ((> y x) (when (or (null highprobe) (< y highprobe)) (setf highprobe y)) (setf y (bisect))) (t (return (+ (log (/ x y) b) (log y b)))))))))) 
From: Raymond Toy <toy.raymond@gm...>  20090117 15:01:04

Kaz Kylheku wrote: > Here is a crazy function I hacked up > I didn't inspect your function too closely, but what I did with cmucl was to compute log2(x) and log2(y) carefully. Then (log x y) = (log2(x)log2(y))/log(2). This is relatively easy since x = 2^n*f, where f is some rational such that 1/2<f<=1. Computing the log of f is easy since we can convert it to a float. For best precision, it's best to keep log2(x) in two parts: the exponent n and the fraction log2(f). (Think what happens if x is very, very large and we add n+log2(f)). This would, of course, need adjustment with clisp if you want to be able to return rationals too. Ray 