On Tue, Aug 7, 2012 at 8:38 PM, Lawrence Crowl <[email protected]> wrote:
> On 8/7/12, Richard Guenther <[email protected]> wrote:
>> On Tue, Aug 7, 2012 at 2:35 AM, Lawrence Crowl <[email protected]> wrote:
>> > Convert double_int from a struct with function into a class with
>> > operators and methods.
>> >
>> > This patch adds the methods and operators. In general functions of
>> > the form "double_int_whatever" become member functions "whatever" or,
>> > when possible, operators.
>> >
>> > Every attempt has been made to preserve the existing algorithms, even
>> > at the expense of some optimization opportunities. Some examples:
>> >
>> > The ext operation takes a value and returns a value. However, that
>> > return value is usually assigned to the original variable. An
>> > operation that modified a variable would be more efficient.
>>
>> That's not always the case though and I think the interface should be
>> consistent with existing behavior to avoid errors creeping in during the
>> transition.
>
> We should probably think about naming conventions for mutating operations,
> as I expect we will want them eventually.
Right. In the end I would prefer explicit constructors.
>> > In some cases, an outer sign-specific function calls an inner
>> > function with the sign as a parameter, which then decides which
>> > implementation to do. Decisions should not be artificially
>> > introduced, and the implementation of each case should be exposed as
>> > a separate routine.
>> >
>> > The existing operations are implemented in terms of the new
>> > operations, which necessarily adds a layer between the new code and
>> > the existing users. Once all files have migrated, this layer will
>> > be removed.
>> >
>> > There are several existing operations implemented in terms of even
>> > older legacy operations. This extra layer has not been removed.
>> >
>> > On occasion though, parameterized functions are often called
>> > with a constant argments. To support static statement of intent,
>> > and potentially faster code in the future, there are several new
>> > unparameterized member functions. Some examples:
>> >
>> > Four routines now encode both 'arithmetic or logical' and 'right or
>> > left' shift as part of the funciton name.
>> >
>> > Four routines now encode both 'signed or unsigned' and 'less than or
>> > greater than' as part of the function name.
>>
>> For most parts overloads that take an (unsigned) HOST_WIDE_INT argument
>> would be nice, as well as the ability to say dbl + 1.
>
> Hm. There seems to be significant opinion that there should not be any
> implicit conversions. I am okay with operations as above, but would like
> to hear the opinions of others.
Well, I'd simply add
double_int operator+(HOST_WIDE_INT);
double_int operator+(unsigned HOST_WIDE_INT);
and be done with it ;) Yes, a tad bit more inconvenient on the implementation
side compared to a non-explicit constructor from HOST_WIDE_INT or a
conversion operator ... but adhering to the rule that we do _not_ want such
automatic conversions (well, yet, for the start).
>> > -typedef struct
>> > +typedef struct double_int
>> > {
>> > +public:
>> > + /* Normally, we would define constructors to create instances.
>> > + Two things prevent us from doing so.
>> > + First, defining a constructor makes the class non-POD in C++03,
>> > + and we certainly want double_int to be a POD.
>> > + Second, the GCC conding conventions prefer explicit conversion,
>> > + and explicit conversion operators are not available until C++11.
>> > */
>> > +
>> > + static double_int make (unsigned HOST_WIDE_INT cst);
>> > + static double_int make (HOST_WIDE_INT cst);
>> > + static double_int make (unsigned int cst);
>> > + static double_int make (int cst);
>>
>> Did we somehow decide to not allow constructors? It's odd to convert to
>> C++ and end up with static member functions resembling them ...
>
> Constructors are allowed, but PODs are often passed more efficiently.
> That property seemed particularly important for double_int.
True - I forgot about this issue. Same for the return values. I suppose we
need to inspect code quality before going this route.
>> Also I believe the conversion above introduces possible migration errors.
>> Think of a previous
>>
>> HOST_WIDE_INT a;
>> double_int d = uhwi_to_double_int (a);
>>
>> if you write that now as
>>
>> HOST_WIDE_INT a;
>> double_int d = double_int::make (a);
>>
>> you get the effect of shwi_to_double_int. Oops.
>
> Hm. I think the code was more likely to be wrong originally,
> but I take your point.
>
>> So as an intermediate
>> I'd like you _not_ to introduce the make () overloads.
>
> Okay.
>
>> Btw, if HOST_WIDE_INT == int the above won't even compile.
>
> Is that true of any host? I am not aware of any. Anyway, it is
> moot if we remove the overloads.
Right. I'd simply rely on int / unsigned int promotion to HOST_WIDE_INT
or unsigned HOST_WIDE_INT and only provide overloads for HOST_WIDE_INT
kinds anyway.
Richard.
> --
> Lawrence Crowl