
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