#407 TANH floating point overflow for large short or single float

lisp error
closed-fixed
clisp (525)
5
2008-03-27
2007-03-19
No

(TANH 1.0s3) => floating point overflow

(TANH 1.0f3) => floating point overflow

(TANH 1.0d3) => 1.0d0 (OK)

(TANH 1.0l3) => 1.0L0 (OK)

Clisp 2.38 / Linux. I looked at the Changelog and didn't see anything about TANH. Hope this helps.

Discussion

  • Sam Steingold

    Sam Steingold - 2007-03-19

    Logged In: YES
    user_id=5735
    Originator: NO

    (exp 1.0l3) ==> 1.9700711140170469939L434
    which is bigger than most-positive-double-float (1.7976931348623157E308)
    thus you cannot expect tanh to work on this number for D, F, S.
    the reason (TANH 1.0d3) works is that cosh and sinh are computed (and divided) in long precision and then the result is converted to doubles, so it works "through the back door".

     
  • Sam Steingold

    Sam Steingold - 2007-03-19
    • assigned_to: haible --> sds
    • status: open --> pending-invalid
     
  • Sam Steingold

    Sam Steingold - 2007-03-19

    Logged In: YES
    user_id=5735
    Originator: NO

    This bug report is now marked as "pending"/"invalid".
    This means that we think that the problem you report
    is not a problem with CLISP.
    Unless you - the reporter - act within 2 weeks,
    the bug will be permanently closed.
    Sorry about the inconvenience -
    we hope your silence means that
    you agree that this is not a bug in CLISP.

     
  • Robert Dodier

    Robert Dodier - 2007-03-19
    • status: pending-invalid --> open
     
  • Robert Dodier

    Robert Dodier - 2007-03-19

    Logged In: YES
    user_id=501686
    Originator: YES

    "(exp 1.0l3) ==> 1.9700711140170469939L434
    which is bigger than most-positive-double-float (1.7976931348623157E308)
    thus you cannot expect tanh to work on this number for D, F, S."

    Um, this only shows that computing tanh from (exp(x) - exp(-x))/(exp(x) + exp(-x)) isn't always a good idea. There are other formulas. If nothing else, Clisp could check the argument to see if abs(x) > (some precision-dependent limit) and return 1 in that case.

    Probably if x is complex the test would be on abs(Re(x)) although I don't know off the top of my head what the appropriate result is.

     
  • Raymond Toy

    Raymond Toy - 2008-03-27

    Logged In: YES
    user_id=28849
    Originator: NO

    A reasonable way for computing tanh(x):

    if x < 0 then -tanh(-x)
    if x >= 0 then
    D(2*x)/(2+D(2*x))

    where D(x) = exp(x) - 1. It looks like F_expx_F computes exp(x). I think a minor tweak will produce exp(x)-1.

    I can help implement this if someone helps me understand how the internals work.

     
  • Robert Dodier

    Robert Dodier - 2008-03-27

    Logged In: YES
    user_id=501686
    Originator: YES

    About D(2*x)/(2+D(2*x)), it seems like that is susceptible to overflow just like the current implementation. Rewriting with negative exponents might help, although Clisp seems to cough up an underflow error for the exponential of a large negative exponent.

    There are probably asymptotic series or rational function approximations or some other formulas in A&S; I haven't looked.

     
  • Raymond Toy

    Raymond Toy - 2008-03-27

    Logged In: YES
    user_id=28849
    Originator: NO

    Oops. That was for solving issues near 0, which clisp doesn't have. I think a better scheme would be (1-exp(-2*x))/(1+exp(-2*x)) = 1 - 2*exp(-2*x)/(1+exp(-2*x)) for x >> 0.

    Just need to either turn off the underflow warning or check that x is so large that exp(-2*x) would underflow to zero.

    I guess -D(-2*x)/(2+D(-2*x)) would also work for all x >= 0.

     
  • Sam Steingold

    Sam Steingold - 2008-03-27

    Logged In: YES
    user_id=5735
    Originator: NO

    thank you for your bug report.
    the bug has been fixed in the CVS tree.
    you can either wait for the next release (recommended)
    or check out the current CVS tree (see http://clisp.cons.org\)
    and build CLISP from the sources (be advised that between
    releases the CVS tree is very unstable and may not even build
    on your platform).

     
  • Sam Steingold

    Sam Steingold - 2008-03-27
    • status: open --> closed-fixed
     
  • Raymond Toy

    Raymond Toy - 2008-03-27

    Logged In: YES
    user_id=28849
    Originator: NO

    From the logs, I see you implemented this as (1-exp(-2*x))/(1+exp(-2*x)). This fixes the overflow problem, but now you have an accuracy problem for x near 0 since exp(-2*x) is approximately 1.

    I think you need to implement some variant of D(x) = exp(x)-1 by modifying the exp function with the initial sum of 0 instead of 1.

    Then use -D(-2*x)/(2+D(-2*x)) to compute tanh(x).

    Or for x small, say <= 1/2, use the original sinh/cosh, since clisp has an accurate sinh for small x.

     
  • Raymond Toy

    Raymond Toy - 2008-03-27

    Logged In: YES
    user_id=28849
    Originator: NO

    I did look a little at 1684969. I can't reproduce the issue with clisp 2.42 on sparc. More commentss there.

     

Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

JavaScript is required for this form.





No, thanks