Le 24/08/2012 01:35, Gilles Sadowski a écrit :
> On Thu, Aug 23, 2012 at 12:00:56PM -0700, Phil Steitz wrote:
>> On 8/23/12 5:37 AM, Luc Maisonobe wrote:
>>> Le 23/08/2012 13:37, Gilles Sadowski a écrit :
>>>> On Thu, Aug 23, 2012 at 12:35:18PM +0200, Sébastien Brisard wrote:
>>>>> Hi Gilles,
>>>>>
>>>>> 2012/8/23 Gilles Sadowski <gil...@harfang.homelinux.org>:
>>>>>> On Thu, Aug 23, 2012 at 10:05:10AM +0200, Sébastien Brisard wrote:
>>>>>>> Hi Luc,
>>>>>>>
>>>>>>> 2012/8/23 Luc Maisonobe <luc.maison...@free.fr>:
>>>>>>>> Le 23/08/2012 05:16, Sébastien Brisard a écrit :
>>>>>>>>> Hi,
>>>>>>>>> in MATH-849, I have proposed an implementation of Gamma(x)
>>>>>>>>> (previously, class Gamma had only logGamma(x)). Gamma(x) is not
>>>>>>>>> defined for x negative integer. In such instances, I would like to
>>>>>>>>> throw an exception instead of returning Double.NaN. However, creating
>>>>>>>>> a new exception in o.a.c.m.exception seems exagerated, since it's very
>>>>>>>>> unlikely that this exception should be used elsewhere (or maybe).
>>>>>>>>> Should I define a nested exception instead [1]?
>>>>>>>>>
>>>>>>>>> What do you think of the name "UnexpectedNegativeIntegerException"? It
>>>>>>>>> does not really match the pattern of already defined exceptions, but I
>>>>>>>>> can't find a better name.
>>>>>>>> Don't we already have NotPositiveException?
>>>>>>>>
>>>>>>>> Luc
>>>>>>>>
>>>>>>> We do, but Gamma is defined for all negative values, except integer 
>>>>>>> ones...
>>>>>> I think that in some circumstances, it might be useful to not throw
>>>>>> exceptions...
>>>>>> FastMath's "log" returns NaN for negative input.
>>>>>>
>>>>> then I guess that logGamma(x) should also return NaN if x <= 0?
>>>> Anyways, that's what it does currently.
>>>>
>>>>> I have to say I do not really like this option.
>>>> So did you intend to change that?
>>>>
>>>>> My life would
>>>>> sometimes be much easier if NaNs didn't exist... the good old days of
>>>>> the "floating-point error".
>>
>> We have different memories - I am old enough to remember wasting
>> real money due to jobs failing on "floating point checks" when I
>> would have preferred to have computations complete and return NaN
>> (which had not been invented yet).
>>
>>>> IIRC NaN could be useful for example in an optimization algorithm; excerpt
>>>> from Kahan:
>>>> ---
>>>> [...] NaNs is an opportunity ( not obligation ) for software ( especially
>>>> when searching ) to follow an unexceptional path ( no need for exotic
>>>> control structures ) to a point where an exceptional event can be appraised
>>>> after the event, when additional evidence may have accrued. [...]
>>>> ---
>>>>
>>>> I do not say that Commons Math should prefer NaN over throwing exceptions.
>>> If the choice is allowed would really prefer NaN for such cases.
>>
>> +1
>>>
>>>> Maybe that it depends on how high-level an application is (i.e. if there 
>>>> are
>>>> already calls to methods that could throw exceptions, then an algorithm 
>>>> that
>>>> would not use try/catch to protect itself would fail anyway).
>>>> If we want Commons Math to allow taking advantage of NaNs, it would 
>>>> probably
>>>> need to be updated so that a lot of precondition checks ought to be removed
>>>> (but this will likely lead to reduced robustness in some applications that
>>>> do not do their own checks...).
>>> This would clearly be cumbersome for users.
>>> Since we have changed our exception hierarchy, we don't have a single
>>> root anymore, so users simply cannot catch all exception we throw at
>>> once, they have to check every single type, and make sure they are
>>> thrown by themselves without any help from compiler.
>>>
>>> Just adding new exceptions is too much, we have already gone too far
>>> this way.
>>
>> +1 and the fact that all exceptions are unchecked makes it even
>> harder for client apps as the compiler will not help / force them. 
> 
> For those new to this list, they can search the archive for lengthy
> discussions on this subject.
> The summary is that CM has absolutely no use of checked exceptions.

Another really important part is that CM doesn't have anymore a
hierarchy of exception. It has a bunch of completely unrelated
exceptions, all extending different standard Java exceptions. This is
the part that really bothers me, but this is the current consensus.

> Client apps cannot do more with checked exceptions, and can be made as
> "safe" by wrapping calls in try-blocks.
> On the other hand, client source code is much cleaner without unnecessary
> "throws" clauses or wrapping of checked expections at all levels.
> Some Java experts go as far as saying that checked exceptions were a
> language design mistake (never repeated in languages invented more
> recently).
> 
>> There is a reason that NaNs exist.  It is much cheaper to return a
>> NaN than to raise (and force the client to handle) an exception. 
>> This is not precise and probably can't be made so, but I have always
>> looked at things more or less like this:
>>
>> 0) IAE (which I see no need to specialize as elaborately as we have
>> done in [math]) is for clear violation of the documented API
>> contract.  The actual parameters "don't make sense" in the context
>> of the API.
> 
> The "elaboration" is actually very basic (but that's a matter of taste), but
> it was primarily promoted (by me) in order to hide (as much as possible) the
> ugliness (another matter of taste) of the "LocalizedFormats" enum, and its
> inconsequent use (duplication). [Cf. discussions in the archive.]
> 
>> 1) NaN can be returned as the result of a computation which, when
>> started with legitimate arguments, does not result in a
>> representable value.
> 
> According to this description, Sébastien's case _must_ be handled by an
> exception: the argument is _not_ legtimate.
> The usage of NaN I was referring to is to let a computation proceed ("follow
> an unexceptional path") in the hope that the final result might still be
> meaningful.
> If the NaN persists, not checking for it and signalling the problem (i.e.
> raise an exception) is a bug. This is to avoid that (and be robust) that we
> do extensive precondition checks in CM. But this has the unavoidable
> drawback that the use of NaN as suggested is much less likely to be feasible
> when calling CM code. Once realizing that, it becomes much less obvious that
> there is _any_ advantage of letting NaNs propagate...
> [Anyone has an example of NaN usage? Please let me know.]

I use NaN a lot as an indicator that a variable has not been fully
initialized yet. This occurs for example in iterative algorithms, where
some result is computed deep inside some loop and we don't know when the
loop will end. Then I write something along these lines:

  while (Double.isNaN(result)) {
     // do something that hopefully will change result to non-NaN
  }

  // now I know result has been computed

Another use is to initialize some fields in class to values I know are
not meaningful. I can then us NaN as a marker to do lazy evaluation for
values that takes time to compute and should be computed only when both
really needed and when everything required for their computation is
available.

Another use is simply to detect some special cases in computations (like
sqrt(-1) or 0/0). I do the computation first and check the NaN
afterwards. See for example the detection of NaNs in the linear
combinations in MathArrays or in the nth order Brent solver.

Another use of NaNs occurs when integrating various code components from
different origins in a single application. Data is forwarded between the
various components in all directions. Components never share the same
exceptions mechanisms. Components either process NaNs specially (which
is good) or they let the processor propagate them (it is what the IEEE
standard mandates) and at the end you can detect it reliably at
application level.

> 
>> The problem is that contracts can often be written so that instances
>> of 1) are turned into instances of 0).  Gamma(-) is a great
>> example.  The singularities at negative integers could be viewed as
>> making negative integer arguments "illegal" or "nonsense" from the
>> API standpoint,
> 
> They are just nonsense (not just from an API standpoint).
> 
>> or legitimate arguments for which no well-defined,
>> representable value can be returned.  Personally, I would prefer to
>> get NaN back from this function and just point out the existence of
>> the singularities in the javadoc.
> 
> This is consistent with how basic math functions behave, but not with the
> general rule/convention of most of CM code.
> It may be fine that we have several ways to deal with exceptional
> conditions, but it might be nice, as with formatting, to have rules so that
> we know how to write contributions.

Too many rules are not a solution, especially when there are no tools to
help enforce these rules are obeyed. Relying only on the fact human
proof-reading will enforce them is wishful thinking.

Luc

> 
> 
> Gilles
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
> For additional commands, e-mail: dev-h...@commons.apache.org
> 
> 


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@commons.apache.org
For additional commands, e-mail: dev-h...@commons.apache.org

Reply via email to