Boost logo

Boost :

Subject: Re: [boost] New Boost.XInt Library, request preliminary review
From: Jeffrey Lee Hellrung, Jr. (jhellrung_at_[hidden])
Date: 2010-03-29 03:22:55


Chad Nelson wrote:
> On 03/29/2010 01:11 AM, Jeffrey Lee Hellrung, Jr. wrote:
>
>>>> If that's the purpose of your NaN, why limit your set of "special"
>>>> values to just { NaN }, when under some circumstances returning some
>>>> representation of infinity (or +infinity or -infinity if you make
>>>> such a distinction) would be more informative? For example, you can
>>>> make n/0 for n != 0 result in infinity,
>>> I could, but why? Who needs to know that n/0 is specifically infinity,
>>> rather than simply NaN? If you can point out a case where it would help
>>> someone more than returning a NaN would, I'll be happy to add it.
>> An xint::integer which is +infinity or -infinity is more meaningful than
>> one which is NaN.
>
> Agreed -- but only slightly. It carries one additional bit's worth of
> meaning, the sign.

Even if you identify +infinity and -infinity as a single infinity, it
should *still* mean something different from an NaN. You might group
infinity into the class of NaNs, but that doesn't mean that every
operation which results in an NaN may as well result in an infinity
(signed or unsigned). 0/0 and sqrt(-1) should evaluate to an NaN (or
throw); it would be unsettling to evaluate these as infinity.

>> At the very least, you can make more refined calculations and
>> comparisons with +/-infinity (compared to NaN),
>
> Do you have an example where this would make any noticeable difference
> in XInt?

Noticeable in what sense? 1/NaN is NaN; 1/+infinity is +0 (or
1/infinity is 0 if you don't want signed infinities and zeros).
Assuming, of course, you allow calculations with NaNs.

>> constructing intervals where either or both endpoints are
>> +/-infinity, etc.
>
> An interval consists of two points. Setting the lower point to
> Not-a-Number would work exactly the same as setting it to -infinity.
> Same with the higher point and +infinity. It wouldn't make any sense to
> set the lower point to +infinity, or the higher one to -infinity, so the
> sign doesn't convey any useful information in that case.

Since NaN compares false to anything else, good luck getting your
intervals with NaN endpoints to work in any kind of generic setting ;)

>> You might feel that an infinity value belongs in a wrapper class around
>> xint::integer, and I would tend to agree.
>
> I don't see a need for an infinity value at all. It provides no value to
> any function presently in the library, or any function I can imagine,
> that isn't already provided by Not-a-Number.

Yes, this is true. I keep thinking that your NaN should be quiet, but
the current state of affairs (non-blockable throwing when you do just
about anything with an NaN) presents fewer use cases for infinities.

>> But I would also put the NaN representation in this wrapper class as
>> well, along with the entire exception blocking framework. It seems
>> to me to be orthogonal to the rest of the interface, and if one never
>> uses blocking exceptions, it seems like a waste.
>
> Not completely. There *are* the two functions that return Not-a-Number
> as part of their normal operation, not counting the string- and
> stream-reading functions. As I said on the rationales page of the
> documentation, I tried using Boost.Optional for those, but it made the
> library harder for people not already familiar with Boost.Optional to
> understand. An error code is an idiom that every C or C++ developer
> already understands well and knows how to deal with.

Which 2 functions? invmod and random_prime? These hardly seem like
fundamental operations that necessitate this "invasion" into an
otherwise pure big-integer interface ;) Returning optional values is
precisely the raison d'etre of Boost.Optional, and you're ending up just
building its functionality directly into the xint::integer class, so
instead of xint::integer, we really have a boost::optional<
xint::integer >. I don't like that :/ What did you find about
Boost.Optional that was difficult for users to understand?

> I could move the Not-a-Number value and the exception-blocking system to
> a wrapper, and go back to using Boost.Optional for those two functions,
> neophyte users be damned. Or have them throw exceptions, though the idea
> is distasteful to me. But I'm not yet convinced that there's sufficient

Returning a Boost.Optional seems perfectly reasonable.

> reason to do so... though I must admit, the idea is appealing from a
> design perspective, as it would make the interface noticeably more
> elegant. Scott McMurray's point about the existence of Not-a-Number
> forcing the library to check for it in all functions is an argument in
> its favor as well.
>
> Keep going, one more valid argument might be enough to change my mind. :-)

The interface to invmod and random_prime should be built around the
interface of xint::integer, not the other way around.

>> Also, why does invmod always return an NaN on an invalid inverse, and
>> not throw a blockable exception?
>
> Because exceptions should, to my mind, be reserved for exceptional
> behavior -- things that should never happen under normal circumstances,
> and which demand special handling. Unless the specified modulus is
> prime, which cannot be trivially determined, invmod is *expected* to
> discover that some numbers have no inverse for it. That's neither
> unexpected nor exceptional, and depending on the application, doesn't
> automatically require special handling.

I sympathize with this reasoning. Generally speaking, if the user
cannot trivially check the preconditions, it could make sense to return
some kind of error condition rather than throwing.

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk