lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] using log1p(-1)


From: Greg Chicares
Subject: Re: [lmi] using log1p(-1)
Date: Wed, 19 May 2010 16:29:25 +0000
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

On 2010-05-19 15:13Z, Vadim Zeitlin wrote:
> 
>  math_functors_test.cpp currently calls i_upper_12_over_12_from_i(-1) which
> results in a call to log1p(-1).

This test is valid and important, because an interest rate of -100% is
actually possible, and it must have the correct effect (in lay terms,
you lose all your money):

    // Test interest rate of -100%.

    BOOST_TEST_EQUAL(-1.0 , i_upper_12_over_12_from_i_naive<double>()(-1.0));
    BOOST_TEST_EQUAL(-1.0 , i_upper_12_over_12_from_i      <double>()(-1.0));

This test only ensures that we get a NaN with nonsensical input,
although throwing an exception might be a whole lot better
(because we wouldn't have to trace where the NaN came from):

    // Test nonsensical interest rate of -101%.

    BOOST_TEST(lmi_isnan(i_upper_12_over_12_from_i_naive<double>()(-1.01)));
    BOOST_TEST(lmi_isnan(i_upper_12_over_12_from_i<double>()      (-1.01)));

> When using the Boost version of the
> function, passing -1 to it results in an std::overflow_error exception
> being thrown resulting in a test failure. This behaviour seems to be
> reasonable because POSIX says that "If x is -1, a pole error shall occur"
> (see [1]) and while C99 only says "A range error _may_ occur if the
> argument equals -1" (emphasis mine, see 7.12.6.9/2 of ISO/IEC 9899:1999(E))
> most if not all of the existing C99 implementations also conform to POSIX
> and so do treat this as error. So, again, throwing an exception looks like
> the right thing to do. And it seems even more right for the next test after
> one which calls log1p(-1.01). Here C99 and POSIX agree that this shall
> result in a domain error.

Then we should add special-case code for -1 (returning the correct
answer directly without calling transcendental functions that are
permitted to signal errors in that case), and for numbers that are
more negative than -1 (throwing an exception). We already have
special-case code like that in the same file, in coi_rate_from_q().

IOW, AFAIK, we don't rely on getting a NaN instead of an exception.

>  Boost allows to configure what happens in this case (in several different
> ways, see [2]) and so in principle we could avoid throwing this exception
> but would this be the right thing to do? IMHO if we really need to allow
> passing -1 (or inferior) values to i_upper_12_over_12_from_i() it would be
> better to handle these cases directly in it instead of changing the
> behaviour of the global log1p() function. Especially because doing this
> would likely be non-trivial.

Yes, I think we're both saying the same thing.

Overflow (with expm1()) is another possible mode of failure, but
I see no really good reason for worrying about it. For one thing,
interest rates are generally constrained to a "plausible" range,
so it's probably impossible for even a clever and malicious user
to use overflow to create a failing testcase. For another, I think
we'd just get an INF, or a NaN, or some sort of HUGEVAL that would
reliably prevent a bogus illustration from being produced. But if
you want to guard against this in some reasonably simple way, then
I guess that's okay.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]