Boost logo

Boost :

From: Matt Gruenke (mgruenke_at_[hidden])
Date: 2008-08-01 13:52:43


John C. Femiani wrote:
> Matt Gruenke wrote:
>> John C. Femiani wrote:
>>> Matt Gruenke wrote:
>>>> Speaking of division, while I'd expect /= to return the same type
>>>> as the LHS operand, the way I've previously implemented fixed point
>>>> division is to return:
>>>> result_int_bits = (numer_int_bits + denom_frac_bits + 1)
>>>> result_frac_bits = (numer_frac_bits + denom_int_bits - 1)
>>> So then what happens to the value of X after I say Z = X /=Y?
>>> Do you mean '/', instead of '/='?
>>
>> Yes, I was describing the behavior of my operator/(). I hadn't
>> written an operator/=().
>>
> I think perhaps the issue with division is that rounding policy should
> be rethought. Also:
>> base_type tmp = (base_type)val / (base_type)x.val;
>> val = tmp << (frac_bits);
> should be something like
>
> static const int DENOMINATOR= 1 << frac_bits;
> base_type tmp = rounding_policy::divide(val * DENOMINATOR, x.val);
>
> I think the old way lost a lot of precision because it divided before
> multiplying.e.g.

By replying to my message, it seems like you might be confusing two
implementations. The one I was describing is my own private code, which
worked the way you're suggesting.

> Then for multiplying:
>
>> base_type tmp = (base_type)val * (base_type)x.val;
>> val = tmp >> (frac_bits);
> could possibly be:
>
> val = rounding_policy::divide( val * x.val, DENOMINATOR);

The approach I took for operator*() was to return a larger type that
lost no precision or range from the multiplication. Then the rounding
happens when you assign the result to a smaller type. This both gives
the user a natural way to control how much precision is preserved and
avoids overhead from any unnecessary rounding (i.e. rounding more
frequently than the user might want or need).

Matt


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