On 10/23/12, Kenneth Zadeck <zad...@naturalbridge.com> wrote:
> On 10/23/2012 10:12 AM, Richard Biener wrote:
> > +  inline bool minus_one_p () const;
> > +  inline bool zero_p () const;
> > +  inline bool one_p () const;
> > +  inline bool neg_p () const;
> >
> > what's wrong with w == -1, w == 0, w == 1, etc.?
>
> I would love to do this and you seem to be somewhat knowledgeable
> of c++.  But i cannot for the life of me figure out how to do it.

Starting from the simple case, you write an operator ==.

as global operator:  bool operator == (wide_int w, int i);
as member operator:  bool wide_int::operator == (int i);

In the simple case,

bool operator == (wide_int w, int i)
{
  switch (i)
    {
      case -1: return w.minus_one_p ();
      case  0: return w.zero_p ();
      case  1: return w.one_p ();
      default: unexpected....
    }
}

> say i have a TImode number, which must be represented in 4 ints
> on a 32 bit host (the same issue happens on 64 bit hosts, but
> the examples are simpler on 32 bit hosts) and i compare it to -1.
> The value that i am going to see as the argument of the function
> is going have the value 0xffffffff.  but the value that i have
> internally is 128 bits.  do i take this and 0 or sign extend it?

What would you have done with w.minus_one_p ()?

> in particular if someone wants to compare a number to 0xdeadbeef i
> have no idea what to do.  I tried defining two different functions,
> one that took a signed and one that took and unsigned number but
> then i wanted a cast in front of all the positive numbers.

This is where it does get tricky.  For signed arguments, you should sign
extend.  For unsigned arguments, you should not.  At present, we need
multiple overloads to avoid type ambiguities.

bool operator == (wide_int w, long long int i);
bool operator == (wide_int w, unsigned long long int i);
inline bool operator == (wide_int w, long int i)
  { return w == (long long int) i; }
inline bool operator (wide_int w, unsigned long int i)
  { return w == (unsigned long long int) i; }
inline bool operator == (wide_int w, int i)
  { return w == (long long int) i; }
inline bool operator (wide_int w, unsigned int i)
  { return w == (unsigned long long int) i; }

(There is a proposal before the C++ committee to fix this problem.)

Even so, there is room for potential bugs when wide_int does not
carry around whether or not it is signed.  The problem is that
regardless of what the programmer thinks of the sign of the wide int,
the comparison will use the sign of the int.

> If there is a way to do this, then i will do it, but it is going
> to have to work properly for things larger than a HOST_WIDE_INT.

The long-term solution, IMHO, is to either carry the sign information
around in either the type or the class data.  (I prefer type, but
with a mechanism to carry it as data when needed.)  Such comparisons
would then require consistency in signedness between the wide int
and the plain int.

> I know that double-int does some of this and it does not carry
> around a notion of signedness either.  is this just code that has
> not been fully tested or is there a trick in c++ that i am missing?

The double int class only provides == and !=, and only with other
double ints.  Otherwise, it has the same value query functions that
you do above.  In the case of double int, the goal was to simplify
use of the existing semantics.  If you are changing the semantics,
consider incorporating sign explicitly.

-- 
Lawrence Crowl

Reply via email to