
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. 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); Another way to think of it is that the rounding policy should be a part of the base_type, decoupled from the fixed pt class. Then one can just assume that val * x.val / DENOMINATOR rounds the way the user intended. You can provide separate wrappers that change the bounds as well as the rounding behavior, and your code should be less coupled. To create a fixed point class, I could say: fixed_pt<8,24, bounded_int<int, MIN, MAX, true, true> > or fixed_pt<8,24, with_rounding< nearest, bounded_int<int, MIN, MAX, true, true> > > assuming that you had a template class called 'with_rounding' and a struct for the 'nearest' rounding policy. You can follow the trend of the constrained_value authors and make 'nearest' a function, so that ::boost::function can be used and the rounding policy can be changed at runtime. --John